diff --git a/CHANGES b/CHANGES index 193e9adea6c1336e6df519ffe3c8016bc9acdf84..d83e08ad4bbe2d24495d9894c150dfabf52020be 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,10 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] + *) New ASN1 functions to handle sign, verify, digest, pack and + unpack operations in terms of ASN1_ITEM. + [Steve Henson] + *) New extension functions for OCSP structures, these follow the same conventions as certificates and CRLs. [Steve Henson] diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c index 8257b8639e12f3a6fd2ec8204a93e79f9e06e4fa..fb4686fdbd17c4dfcb7bd93cadb2e377108df8bf 100644 --- a/crypto/asn1/a_digest.c +++ b/crypto/asn1/a_digest.c @@ -88,3 +88,21 @@ int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data, return(1); } + +int ASN1_item_digest(const ASN1_ITEM *it, const EVP_MD *type, void *asn, + unsigned char *md, unsigned int *len) + { + EVP_MD_CTX ctx; + int i; + unsigned char *str = NULL; + + i=ASN1_item_i2d(asn,&str, it); + if (!str) return(0); + + EVP_DigestInit(&ctx,type); + EVP_DigestUpdate(&ctx,str,i); + EVP_DigestFinal(&ctx,md,len); + OPENSSL_free(str); + return(1); + } + diff --git a/crypto/asn1/a_sign.c b/crypto/asn1/a_sign.c index 4c651706d2d6a2acfb345cb0661c2ef54fcef13a..5be077ddfc5a38519e7bf33c957c4a254c489518 100644 --- a/crypto/asn1/a_sign.c +++ b/crypto/asn1/a_sign.c @@ -146,3 +146,76 @@ err: { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); } return(outl); } + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey, + const EVP_MD *type) + { + EVP_MD_CTX ctx; + unsigned char *buf_in=NULL,*buf_out=NULL; + int i,inl=0,outl=0,outll=0; + X509_ALGOR *a; + + for (i=0; i<2; i++) + { + if (i == 0) + a=algor1; + else + a=algor2; + if (a == NULL) continue; + if ( (a->parameter == NULL) || + (a->parameter->type != V_ASN1_NULL)) + { + ASN1_TYPE_free(a->parameter); + if ((a->parameter=ASN1_TYPE_new()) == NULL) goto err; + a->parameter->type=V_ASN1_NULL; + } + ASN1_OBJECT_free(a->algorithm); + a->algorithm=OBJ_nid2obj(type->pkey_type); + if (a->algorithm == NULL) + { + ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_UNKNOWN_OBJECT_TYPE); + goto err; + } + if (a->algorithm->length == 0) + { + ASN1err(ASN1_F_ASN1_SIGN,ASN1_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD); + goto err; + } + } + inl=ASN1_item_i2d(asn,&buf_in, it); + outll=outl=EVP_PKEY_size(pkey); + buf_out=(unsigned char *)OPENSSL_malloc((unsigned int)outl); + if ((buf_in == NULL) || (buf_out == NULL)) + { + outl=0; + ASN1err(ASN1_F_ASN1_SIGN,ERR_R_MALLOC_FAILURE); + goto err; + } + + EVP_SignInit(&ctx,type); + EVP_SignUpdate(&ctx,(unsigned char *)buf_in,inl); + if (!EVP_SignFinal(&ctx,(unsigned char *)buf_out, + (unsigned int *)&outl,pkey)) + { + outl=0; + ASN1err(ASN1_F_ASN1_SIGN,ERR_R_EVP_LIB); + goto err; + } + if (signature->data != NULL) OPENSSL_free(signature->data); + signature->data=buf_out; + buf_out=NULL; + signature->length=outl; + /* In the interests of compatibility, I'll make sure that + * the bit string has a 'not-used bits' value of 0 + */ + signature->flags&= ~(ASN1_STRING_FLAG_BITS_LEFT|0x07); + signature->flags|=ASN1_STRING_FLAG_BITS_LEFT; +err: + memset(&ctx,0,sizeof(ctx)); + if (buf_in != NULL) + { memset((char *)buf_in,0,(unsigned int)inl); OPENSSL_free(buf_in); } + if (buf_out != NULL) + { memset((char *)buf_out,0,outll); OPENSSL_free(buf_out); } + return(outl); + } diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c index 2a11927e5c1c2a68e415dbda002f711dde730c41..be5a27e58b132645f2bf09df2c427084a7e57da0 100644 --- a/crypto/asn1/a_verify.c +++ b/crypto/asn1/a_verify.c @@ -117,3 +117,51 @@ int ASN1_verify(int (*i2d)(), X509_ALGOR *a, ASN1_BIT_STRING *signature, err: return(ret); } + + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature, + void *asn, EVP_PKEY *pkey) + { + EVP_MD_CTX ctx; + const EVP_MD *type; + unsigned char *buf_in=NULL; + int ret= -1,i,inl; + + i=OBJ_obj2nid(a->algorithm); + type=EVP_get_digestbyname(OBJ_nid2sn(i)); + if (type == NULL) + { + ASN1err(ASN1_F_ASN1_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); + goto err; + } + + inl = ASN1_item_i2d(asn, &buf_in, it); + + if (buf_in == NULL) + { + ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_MALLOC_FAILURE); + goto err; + } + + EVP_VerifyInit(&ctx,type); + EVP_VerifyUpdate(&ctx,(unsigned char *)buf_in,inl); + + memset(buf_in,0,(unsigned int)inl); + OPENSSL_free(buf_in); + + if (EVP_VerifyFinal(&ctx,(unsigned char *)signature->data, + (unsigned int)signature->length,pkey) <= 0) + { + ASN1err(ASN1_F_ASN1_VERIFY,ERR_R_EVP_LIB); + ret=0; + goto err; + } + /* we don't need to zero the 'ctx' because we just checked + * public information */ + /* memset(&ctx,0,sizeof(ctx)); */ + ret=1; +err: + return(ret); + } + + diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h index 080bf713c097bb3e8cda038fc2bcee9e1abece17..902aebb0611e75d5b2f2759bdc4ce82a492ddb24 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -852,7 +852,9 @@ STACK *ASN1_seq_unpack(unsigned char *buf, int len, char *(*d2i)(), unsigned char *ASN1_seq_pack(STACK *safes, int (*i2d)(), unsigned char **buf, int *len ); void *ASN1_unpack_string(ASN1_STRING *oct, char *(*d2i)()); +void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it); ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_OCTET_STRING **oct); +ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_OCTET_STRING **oct); void ASN1_STRING_set_default_mask(unsigned long mask); int ASN1_STRING_set_default_mask_asc(char *p); diff --git a/crypto/asn1/asn_pack.c b/crypto/asn1/asn_pack.c index bdf5f130b3a3cd0c5ad7540287ea956602cb5808..0b9ed691a9647fea7fe5778f3effd66b29f5c912 100644 --- a/crypto/asn1/asn_pack.c +++ b/crypto/asn1/asn_pack.c @@ -117,7 +117,7 @@ void *ASN1_unpack_string (ASN1_STRING *oct, char *(*d2i)()) /* Pack an ASN1 object into an ASN1_STRING */ -ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) +ASN1_STRING *ASN1_pack_string(void *obj, int (*i2d)(), ASN1_STRING **oct) { unsigned char *p; ASN1_STRING *octmp; @@ -143,3 +143,45 @@ ASN1_STRING *ASN1_pack_string (void *obj, int (*i2d)(), ASN1_STRING **oct) return octmp; } +/* ASN1_ITEM versions of the above */ + +ASN1_STRING *ASN1_pack_item(void *obj, const ASN1_ITEM *it, ASN1_STRING **oct) +{ + ASN1_STRING *octmp; + + if (!oct || !*oct) { + if (!(octmp = ASN1_STRING_new ())) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + if (oct) *oct = octmp; + } else octmp = *oct; + + if(octmp->data) { + OPENSSL_free(octmp->data); + octmp->data = NULL; + } + + if (!(octmp->length = ASN1_item_i2d(obj, &octmp->data, it))) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ASN1_R_ENCODE_ERROR); + return NULL; + } + if (!octmp->data) { + ASN1err(ASN1_F_ASN1_PACK_STRING,ERR_R_MALLOC_FAILURE); + return NULL; + } + return octmp; +} + +/* Extract an ASN1 object from an ASN1_STRING */ + +void *ASN1_unpack_item(ASN1_STRING *oct, const ASN1_ITEM *it) +{ + unsigned char *p; + void *ret; + + p = oct->data; + if(!(ret = ASN1_item_d2i(NULL, &p, oct->length, it))) + ASN1err(ASN1_F_ASN1_UNPACK_STRING,ASN1_R_DECODE_ERROR); + return ret; +} diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index 24ba8618c2a7d64b3e44cb6fbd78eff5dd3dad33..332cad553ae817c93993f5dd3afa81e494b994ba 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -913,6 +913,16 @@ int ASN1_digest(int (*i2d)(),const EVP_MD *type,char *data, int ASN1_sign(int (*i2d)(), X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *signature, char *data,EVP_PKEY *pkey, const EVP_MD *type); + +int ASN1_item_digest(const ASN1_ITEM *it,const EVP_MD *type,void *data, + unsigned char *md,unsigned int *len); + +int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *algor1, + ASN1_BIT_STRING *signature,void *data,EVP_PKEY *pkey); + +int ASN1_item_sign(const ASN1_ITEM *it, X509_ALGOR *algor1, X509_ALGOR *algor2, + ASN1_BIT_STRING *signature, + void *data, EVP_PKEY *pkey, const EVP_MD *type); #endif int X509_set_version(X509 *x,long version);