diff --git a/CHANGES b/CHANGES index a19f241bb4..8ccb3b9c08 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,12 @@ Changes between 0.9.6 and 0.9.7 [xx XXX 2000] + *) Various new functions. EVP_Digest() combines EVP_Digest{Init,Update,Final}() + in a single operation. X509_get0_pubkey_bitstr() extracts the public_key + structure from a certificate. X509_pubkey_digest() digests tha public_key + contents: this is used in various key identifiers. + [Steve Henson] + *) Tolerate nonRepudiation as being valid for S/MIME signing and certSign keyUsage if basicConstraints absent for a CA. [Steve Henson] diff --git a/apps/ocsp.c b/apps/ocsp.c index eaba15f309..cec2f2b809 100644 --- a/apps/ocsp.c +++ b/apps/ocsp.c @@ -525,7 +525,7 @@ static int add_ocsp_serial(OCSP_REQUEST **req, char *serial, X509 *issuer, if(!*req) *req = OCSP_REQUEST_new(); if(!*req) goto err; iname = X509_get_subject_name(issuer); - ikey = issuer->cert_info->key->public_key; + ikey = X509_get0_pubkey_bitstr(issuer); sno = s2i_ASN1_INTEGER(NULL, serial); if(!sno) { diff --git a/crypto/asn1/a_digest.c b/crypto/asn1/a_digest.c index 6c12249d2c..3243beadd2 100644 --- a/crypto/asn1/a_digest.c +++ b/crypto/asn1/a_digest.c @@ -74,7 +74,6 @@ int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data, unsigned char *md, unsigned int *len) { - EVP_MD_CTX ctx; int i; unsigned char *str,*p; @@ -83,9 +82,7 @@ int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data, p=str; i2d(data,&p); - EVP_DigestInit(&ctx,type); - EVP_DigestUpdate(&ctx,str,i); - EVP_DigestFinal(&ctx,md,len); + EVP_Digest(str, i, md, len, type); OPENSSL_free(str); return(1); } @@ -96,16 +93,13 @@ int ASN1_digest(int (*i2d)(), const EVP_MD *type, char *data, 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); + EVP_Digest(str, i, md, len, type); OPENSSL_free(str); return(1); } diff --git a/crypto/asn1/n_pkey.c b/crypto/asn1/n_pkey.c index 82a621224b..c7b92e3a5d 100644 --- a/crypto/asn1/n_pkey.c +++ b/crypto/asn1/n_pkey.c @@ -196,14 +196,11 @@ int i2d_RSA_NET(const RSA *a, unsigned char **pp, int (*cb)(), int sgckey) i = strlen((char *)buf); /* If the key is used for SGC the algorithm is modified a little. */ if(sgckey) { - EVP_MD_CTX mctx; - EVP_DigestInit(&mctx, EVP_md5()); - EVP_DigestUpdate(&mctx, buf, i); - EVP_DigestFinal(&mctx, buf, NULL); + EVP_Digest(buf, i, buf, NULL, EVP_md5()); memcpy(buf + 16, "SGCKEYSALT", 10); i = 26; } - + EVP_BytesToKey(EVP_rc4(),EVP_md5(),NULL,buf,i,1,key,NULL); memset(buf,0,256); @@ -287,10 +284,7 @@ static RSA *d2i_RSA_NET_2(RSA **a, ASN1_OCTET_STRING *os, i = strlen((char *)buf); if(sgckey){ - EVP_MD_CTX mctx; - EVP_DigestInit(&mctx, EVP_md5()); - EVP_DigestUpdate(&mctx, buf, i); - EVP_DigestFinal(&mctx, buf, NULL); + EVP_Digest(buf, i, buf, NULL, EVP_md5()); memcpy(buf + 16, "SGCKEYSALT", 10); i = 26; } diff --git a/crypto/evp/digest.c b/crypto/evp/digest.c index c560733568..5c75a347b8 100644 --- a/crypto/evp/digest.c +++ b/crypto/evp/digest.c @@ -89,4 +89,14 @@ int EVP_MD_CTX_copy(EVP_MD_CTX *out, EVP_MD_CTX *in) } memcpy((char *)out,(char *)in,in->digest->ctx_size); return 1; -} +} + +int EVP_Digest(void *data, unsigned int count, + unsigned char *md, unsigned int *size, const EVP_MD *type) +{ + EVP_MD_CTX ctx; + EVP_DigestInit(&ctx, type); + EVP_DigestUpdate(&ctx, data, count); + EVP_DigestFinal(&ctx, md, size); + return 1; +} diff --git a/crypto/evp/evp.h b/crypto/evp/evp.h index 17a0f306eb..60578f9d5e 100644 --- a/crypto/evp/evp.h +++ b/crypto/evp/evp.h @@ -559,6 +559,8 @@ void EVP_DigestInit(EVP_MD_CTX *ctx, const EVP_MD *type); void EVP_DigestUpdate(EVP_MD_CTX *ctx,const void *d, unsigned int cnt); void EVP_DigestFinal(EVP_MD_CTX *ctx,unsigned char *md,unsigned int *s); +int EVP_Digest(void *data, unsigned int count, + unsigned char *md, unsigned int *size, const EVP_MD *type); int EVP_read_pw_string(char *buf,int length,const char *prompt,int verify); void EVP_set_pw_prompt(char *prompt); diff --git a/crypto/ocsp/ocsp_lib.c b/crypto/ocsp/ocsp_lib.c index bdd4cfccff..825d023e05 100644 --- a/crypto/ocsp/ocsp_lib.c +++ b/crypto/ocsp/ocsp_lib.c @@ -82,7 +82,7 @@ OCSP_CERTID *OCSP_cert_to_id(const EVP_MD *dgst, X509 *subject, X509 *issuer) #endif iname = X509_get_issuer_name(subject); serial = X509_get_serialNumber(subject); - ikey = issuer->cert_info->key->public_key; + ikey = X509_get0_pubkey_bitstr(issuer); return OCSP_cert_id_new(dgst, iname, ikey, serial); } @@ -97,7 +97,6 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, X509_ALGOR *alg; OCSP_CERTID *cid = NULL; unsigned char md[EVP_MAX_MD_SIZE]; - EVP_MD_CTX ctx; if (!(cid = OCSP_CERTID_new())) goto err; @@ -116,9 +115,7 @@ OCSP_CERTID *OCSP_cert_id_new(const EVP_MD *dgst, if (!(ASN1_OCTET_STRING_set(cid->issuerNameHash, md, i))) goto err; /* Calculate the issuerKey hash, excluding tag and length */ - EVP_DigestInit(&ctx,dgst); - EVP_DigestUpdate(&ctx,issuerKey->data, issuerKey->length); - EVP_DigestFinal(&ctx,md,&i); + EVP_Digest(issuerKey->data, issuerKey->length, md, &i, dgst); if (!(ASN1_OCTET_STRING_set(cid->issuerKeyHash, md, i))) goto err; @@ -186,7 +183,6 @@ OCSP_BASICRESP *OCSP_basic_response_new(int type, X509* cert) { time_t t; OCSP_RESPID *rid; - ASN1_BIT_STRING *bs; OCSP_BASICRESP *rsp = NULL; unsigned char md[SHA_DIGEST_LENGTH]; @@ -205,9 +201,7 @@ OCSP_BASICRESP *OCSP_basic_response_new(int type, X509* cert) /* SHA-1 hash of responder's public key * (excluding the tag and length fields) */ - bs = cert->cert_info->key->public_key; - SHA1(ASN1_STRING_data((ASN1_STRING*)bs), - ASN1_STRING_length((ASN1_STRING*)bs), md); + X509_pubkey_digest(cert, EVP_sha1(), md, NULL); if (!(rid->value.byKey = ASN1_OCTET_STRING_new())) goto err; if (!(ASN1_OCTET_STRING_set(rid->value.byKey, diff --git a/crypto/ocsp/ocsp_vfy.c b/crypto/ocsp/ocsp_vfy.c index 7470f1c048..4ac7e821ec 100644 --- a/crypto/ocsp/ocsp_vfy.c +++ b/crypto/ocsp/ocsp_vfy.c @@ -177,8 +177,6 @@ static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) { int i; unsigned char tmphash[SHA_DIGEST_LENGTH], *keyhash; - ASN1_BIT_STRING *key; - EVP_MD_CTX ctx; X509 *x; /* Easy if lookup by name */ @@ -194,10 +192,7 @@ static X509 *ocsp_find_signer_sk(STACK_OF(X509) *certs, OCSP_RESPID *id) for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); - key = x->cert_info->key->public_key; - EVP_DigestInit(&ctx,EVP_sha1()); - EVP_DigestUpdate(&ctx,key->data, key->length); - EVP_DigestFinal(&ctx,tmphash,NULL); + X509_pubkey_digest(x, EVP_sha1(), tmphash, NULL); if(!memcmp(keyhash, tmphash, SHA_DIGEST_LENGTH)) return x; } @@ -294,9 +289,7 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, if(cid) { const EVP_MD *dgst; - EVP_MD_CTX ctx; X509_NAME *iname; - ASN1_BIT_STRING *ikey; int mdlen; unsigned char md[EVP_MAX_MD_SIZE]; if (!(dgst = EVP_get_digestbyobj(cid->hashAlgorithm->algorithm))) @@ -314,11 +307,7 @@ static int ocsp_match_issuerid(X509 *cert, OCSP_CERTID *cid, return -1; if (memcmp(md, cid->issuerNameHash->data, mdlen)) return 0; - ikey = cert->cert_info->key->public_key; - - EVP_DigestInit(&ctx,dgst); - EVP_DigestUpdate(&ctx,ikey->data, ikey->length); - EVP_DigestFinal(&ctx,md,NULL); + X509_pubkey_digest(cert, EVP_sha1(), md, NULL); if (memcmp(md, cid->issuerKeyHash->data, mdlen)) return 0; diff --git a/crypto/x509/x509.h b/crypto/x509/x509.h index 4b1957253d..c3ec6bf4b5 100644 --- a/crypto/x509/x509.h +++ b/crypto/x509/x509.h @@ -719,6 +719,8 @@ int X509_REQ_sign(X509_REQ *x, EVP_PKEY *pkey, const EVP_MD *md); int X509_CRL_sign(X509_CRL *x, EVP_PKEY *pkey, const EVP_MD *md); int NETSCAPE_SPKI_sign(NETSCAPE_SPKI *x, EVP_PKEY *pkey, const EVP_MD *md); +int X509_pubkey_digest(const X509 *data,const EVP_MD *type, + unsigned char *md, unsigned int *len); int X509_digest(const X509 *data,const EVP_MD *type, unsigned char *md, unsigned int *len); int X509_CRL_digest(const X509_CRL *data,const EVP_MD *type, @@ -937,6 +939,7 @@ int X509_set_notBefore(X509 *x, ASN1_TIME *tm); int X509_set_notAfter(X509 *x, ASN1_TIME *tm); int X509_set_pubkey(X509 *x, EVP_PKEY *pkey); EVP_PKEY * X509_get_pubkey(X509 *x); +ASN1_BIT_STRING * X509_get0_pubkey_bitstr(const X509 *x); int X509_certificate_type(X509 *x,EVP_PKEY *pubkey /* optional */); int X509_REQ_set_version(X509_REQ *x,long version); diff --git a/crypto/x509/x509_cmp.c b/crypto/x509/x509_cmp.c index b147d573d2..7927155791 100644 --- a/crypto/x509/x509_cmp.c +++ b/crypto/x509/x509_cmp.c @@ -264,6 +264,12 @@ EVP_PKEY *X509_get_pubkey(X509 *x) return(X509_PUBKEY_get(x->cert_info->key)); } +ASN1_BIT_STRING *X509_get0_pubkey_bitstr(const X509 *x) + { + if(!x) return NULL; + return x->cert_info->key->public_key; + } + int X509_check_private_key(X509 *x, EVP_PKEY *k) { EVP_PKEY *xk=NULL; diff --git a/crypto/x509/x_all.c b/crypto/x509/x_all.c index 7095a2850e..de53e67493 100644 --- a/crypto/x509/x_all.c +++ b/crypto/x509/x_all.c @@ -379,6 +379,15 @@ X509_NAME_ENTRY *X509_NAME_ENTRY_dup(X509_NAME_ENTRY *ne) return ASN1_item_dup(&X509_NAME_ENTRY_it, ne); } +int X509_pubkey_digest(const X509 *data, const EVP_MD *type, unsigned char *md, + unsigned int *len) + { + ASN1_BIT_STRING *key; + key = X509_get0_pubkey_bitstr(data); + if(!key) return 0; + return EVP_Digest(key->data, key->length, md, len, type); + } + int X509_digest(const X509 *data, const EVP_MD *type, unsigned char *md, unsigned int *len) { diff --git a/crypto/x509v3/v3_skey.c b/crypto/x509v3/v3_skey.c index 58da456cb5..3e1eb05430 100644 --- a/crypto/x509v3/v3_skey.c +++ b/crypto/x509v3/v3_skey.c @@ -104,7 +104,6 @@ static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, ASN1_OCTET_STRING *oct; ASN1_BIT_STRING *pk; unsigned char pkey_dig[EVP_MAX_MD_SIZE]; - EVP_MD_CTX md; unsigned int diglen; if(strcmp(str, "hash")) return s2i_ASN1_OCTET_STRING(method, ctx, str); @@ -130,9 +129,7 @@ static ASN1_OCTET_STRING *s2i_skey_id(X509V3_EXT_METHOD *method, goto err; } - EVP_DigestInit(&md, EVP_sha1()); - EVP_DigestUpdate(&md, pk->data, pk->length); - EVP_DigestFinal(&md, pkey_dig, &diglen); + EVP_Digest(pk->data, pk->length, pkey_dig, &diglen, EVP_sha1()); if(!M_ASN1_OCTET_STRING_set(oct, pkey_dig, diglen)) { X509V3err(X509V3_F_S2I_S2I_SKEY_ID,ERR_R_MALLOC_FAILURE);