/* Function: GetX509NameInfo Used by System.Security.Cryptography.X509Certificates' OpenSslX509CertificateReader as the entire implementation of X509Certificate2.GetNameInfo. Return values: NULL if the certificate is invalid or no name information could be found, otherwise a pointer to a memory-backed BIO structure which contains the answer to the GetNameInfo query */ BIO* GetX509NameInfo( X509* x509, int nameType, int forIssuer) { static const char szOidUpn[] = "1.3.6.1.4.1.311.20.2.3"; if (!x509 || !x509->cert_info || nameType < NAME_TYPE_SIMPLE || nameType > NAME_TYPE_URL) { return NULL; } // Algorithm behaviors (pseudocode). When forIssuer is true, replace "Subject" with "Issuer" and // SAN (Subject Alternative Names) with IAN (Issuer Alternative Names). // // SimpleName: Subject[CN] ?? Subject[OU] ?? Subject[O] ?? Subject[E] ?? Subject.Rdns.FirstOrDefault() ?? SAN.Entries.FirstOrDefault(type == GEN_EMAIL); // EmailName: SAN.Entries.FirstOrDefault(type == GEN_EMAIL) ?? Subject[E]; // UpnName: SAN.Entries.FirsOrDefaultt(type == GEN_OTHER && entry.AsOther().OID == szOidUpn).AsOther().Value; // DnsName: SAN.Entries.FirstOrDefault(type == GEN_DNS) ?? Subject[CN]; // DnsFromAlternativeName: SAN.Entries.FirstOrDefault(type == GEN_DNS); // UrlName: SAN.Entries.FirstOrDefault(type == GEN_URI); if (nameType == NAME_TYPE_SIMPLE) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; if (name) { ASN1_STRING* cn = NULL; ASN1_STRING* ou = NULL; ASN1_STRING* o = NULL; ASN1_STRING* e = NULL; ASN1_STRING* firstRdn = NULL; // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == NID_commonName) { // CN wins, so no need to keep looking. cn = str; break; } else if (nid == NID_organizationalUnitName) { ou = str; } else if (nid == NID_organizationName) { o = str; } else if (nid == NID_pkcs9_emailAddress) { e = str; } else if (!firstRdn) { firstRdn = str; } } ASN1_STRING* answer = cn; // If there was no CN, but there was something, then perform fallbacks. if (!answer && firstRdn) { answer = ou; if (!answer) { answer = o; } if (!answer) { answer = e; } if (!answer) { answer = firstRdn; } } if (answer) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, answer, 0); return b; } } } if (nameType == NAME_TYPE_SIMPLE || nameType == NAME_TYPE_DNS || nameType == NAME_TYPE_DNSALT || nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_UPN || nameType == NAME_TYPE_URL) { int expectedType = -1; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: expectedType = GEN_DNS; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: expectedType = GEN_EMAIL; break; case NAME_TYPE_UPN: expectedType = GEN_OTHERNAME; break; case NAME_TYPE_URL: expectedType = GEN_URI; break; } STACK_OF(GENERAL_NAME)* altNames = X509_get_ext_d2i(x509, forIssuer ? NID_issuer_alt_name : NID_subject_alt_name, NULL, NULL); if (altNames) { int i; for (i = 0; i < sk_GENERAL_NAME_num(altNames); ++i) { GENERAL_NAME* altName = sk_GENERAL_NAME_value(altNames, i); if (altName && altName->type == expectedType) { ASN1_STRING* str = NULL; switch (nameType) { case NAME_TYPE_DNS: case NAME_TYPE_DNSALT: str = altName->d.dNSName; break; case NAME_TYPE_SIMPLE: case NAME_TYPE_EMAIL: str = altName->d.rfc822Name; break; case NAME_TYPE_URL: str = altName->d.uniformResourceIdentifier; break; case NAME_TYPE_UPN: { OTHERNAME* value = altName->d.otherName; if (value) { // Enough more padding than szOidUpn that a \0 won't accidentally align char localOid[sizeof(szOidUpn) + 3]; int cchLocalOid = 1 + OBJ_obj2txt(localOid, sizeof(localOid), value->type_id, 1); if (sizeof(szOidUpn) == cchLocalOid && 0 == strncmp(localOid, szOidUpn, sizeof(szOidUpn))) { //OTHERNAME->ASN1_TYPE->union.field str = value->value->value.asn1_string; } } break; } } if (str) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); sk_GENERAL_NAME_free(altNames); return b; } } } sk_GENERAL_NAME_free(altNames); } } if (nameType == NAME_TYPE_EMAIL || nameType == NAME_TYPE_DNS) { X509_NAME* name = forIssuer ? x509->cert_info->issuer : x509->cert_info->subject; int expectedNid = NID_undef; switch (nameType) { case NAME_TYPE_EMAIL: expectedNid = NID_pkcs9_emailAddress; break; case NAME_TYPE_DNS: expectedNid = NID_commonName; break; } if (name) { // Walk the list backwards because it is stored in stack order for (int i = X509_NAME_entry_count(name) - 1; i >= 0; --i) { X509_NAME_ENTRY* entry = X509_NAME_get_entry(name, i); if (!entry) { continue; } ASN1_OBJECT* oid = X509_NAME_ENTRY_get_object(entry); ASN1_STRING* str = X509_NAME_ENTRY_get_data(entry); if (!oid || !str) { continue; } int nid = OBJ_obj2nid(oid); if (nid == expectedNid) { BIO* b = BIO_new(BIO_s_mem()); ASN1_STRING_print_ex(b, str, 0); return b; } } } } return NULL; }
int X509_CRL_get_signature_nid(const X509_CRL *crl) { return OBJ_obj2nid(crl->sig_alg.algorithm); }
/* From PSS AlgorithmIdentifier set public key parameters. */ static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int ret = 0; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_UNSUPPORTED_SIGNATURE_TYPE); return 0; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) { goto err; } md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) { goto err; } saltlen = 20; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_SALT_LENGTH); goto err; } } /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { OPENSSL_PUT_ERROR(EVP, rsa_pss_to_ctx, EVP_R_INVALID_TRAILER); goto err; } if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey) || !EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) || !EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) || !EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md)) { goto err; } ret = 1; err: RSA_PSS_PARAMS_free(pss); if (maskHash) { X509_ALGOR_free(maskHash); } return ret; }
static int rsa_pss_to_ctx(EVP_MD_CTX *ctx, EVP_PKEY_CTX *pkctx, X509_ALGOR *sigalg, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_PSS_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(pss->maskGenAlgorithm, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(pss->hashAlgorithm); if (!md) goto err; if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* * Could perform more salt length sanity checks but the main RSA * routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* * low-level routines support only trailer field 0xbc (value 1) and * PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (pkey) { if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; } else { const EVP_MD *checkmd; if (EVP_PKEY_CTX_get_signature_md(pkctx, &checkmd) <= 0) goto err; if (EVP_MD_type(md) != EVP_MD_type(checkmd)) { RSAerr(RSA_F_RSA_PSS_TO_CTX, RSA_R_DIGEST_DOES_NOT_MATCH); goto err; } } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_PSS_PARAMS_free(pss); X509_ALGOR_free(maskHash); return rv; }
// Convert a ByteString to an OpenSSL NID int OSSL::byteString2oid(const ByteString& byteString) { const unsigned char *p = byteString.const_byte_str(); return OBJ_obj2nid(d2i_ASN1_OBJECT(NULL, &p, byteString.size())); }
static int parse_pkcs7_data(const options_t *options, const CRYPT_DATA_BLOB *blob) { int result = 0; const cert_format_e input_fmt = CERT_FORMAT_DER; PKCS7 *p7 = NULL; BIO *in = NULL; CRYPTO_malloc_init(); ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); in = BIO_new_mem_buf(blob->pbData, blob->cbData); if (in == NULL) { result = -2; goto error; } switch (input_fmt) { default: EXIT_ERROR("unhandled input format for certificate"); case CERT_FORMAT_DER: p7 = d2i_PKCS7_bio(in, NULL); break; case CERT_FORMAT_PEM: p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); break; } if (p7 == NULL) { ERR_print_errors_fp(stderr); result = -3; goto error; } STACK_OF(X509) *certs = NULL; int type = OBJ_obj2nid(p7->type); switch (type) { default: break; case NID_pkcs7_signed: // PKCS7_type_is_signed(p7) certs = p7->d.sign->cert; break; case NID_pkcs7_signedAndEnveloped: // PKCS7_type_is_signedAndEnveloped(p7) certs = p7->d.signed_and_enveloped->cert; break; } const int numcerts = certs != NULL ? sk_X509_num(certs) : 0; for (int i = 0; i < numcerts; i++) { X509 *cert = sk_X509_value(certs, i); print_certificate(options->certout, options->certoutform, cert); // NOTE: Calling X509_free(cert) is unnecessary. } // Print whether certificate signature is valid if (numcerts > 0) { X509 *subject = sk_X509_value(certs, 0); X509 *issuer = sk_X509_value(certs, numcerts - 1); int valid_sig = X509_verify(subject, X509_get_pubkey(issuer)); output("Signature", valid_sig == 1 ? "valid" : "invalid"); } // Print signers if (numcerts > 0) { output_open_scope("signers", OUTPUT_SCOPE_TYPE_ARRAY); for (int i = 0; i < numcerts; i++) { X509 *cert = sk_X509_value(certs, i); X509_NAME *name = X509_get_subject_name(cert); int issuer_name_len = X509_NAME_get_text_by_NID(name, NID_commonName, NULL, 0); if (issuer_name_len > 0) { output_open_scope("signer", OUTPUT_SCOPE_TYPE_OBJECT); char issuer_name[issuer_name_len + 1]; X509_NAME_get_text_by_NID(name, NID_commonName, issuer_name, issuer_name_len + 1); output("Issuer", issuer_name); output_close_scope(); // signer } } output_close_scope(); // signers } error: if (p7 != NULL) PKCS7_free(p7); if (in != NULL) BIO_free(in); // Deallocate everything from OpenSSL_add_all_algorithms EVP_cleanup(); // Deallocate everything from ERR_load_crypto_strings ERR_free_strings(); return result; }
int test(char *URL) { CURLM* multi; sslctxparm p; CURLMcode res; int running; char done = FALSE; int i = 0; CURLMsg *msg; struct timeval ml_start; struct timeval mp_start; char ml_timedout = FALSE; char mp_timedout = FALSE; if(libtest_arg2) { portnum = atoi(libtest_arg2); } if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) { fprintf(stderr, "curl_global_init() failed\n"); return TEST_ERR_MAJOR_BAD; } if ((p.curl = curl_easy_init()) == NULL) { fprintf(stderr, "curl_easy_init() failed\n"); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } p.accessinfoURL = (unsigned char *) strdup(URL); p.accesstype = OBJ_obj2nid(OBJ_txt2obj("AD_DVCS",0)) ; curl_easy_setopt(p.curl, CURLOPT_URL, p.accessinfoURL); curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun) ; curl_easy_setopt(p.curl, CURLOPT_SSL_CTX_DATA, &p); curl_easy_setopt(p.curl, CURLOPT_SSL_VERIFYPEER, FALSE); curl_easy_setopt(p.curl, CURLOPT_SSL_VERIFYHOST, 1); if ((multi = curl_multi_init()) == NULL) { fprintf(stderr, "curl_multi_init() failed\n"); curl_easy_cleanup(p.curl); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } if ((res = curl_multi_add_handle(multi, p.curl)) != CURLM_OK) { fprintf(stderr, "curl_multi_add_handle() failed, " "with code %d\n", res); curl_multi_cleanup(multi); curl_easy_cleanup(p.curl); curl_global_cleanup(); return TEST_ERR_MAJOR_BAD; } fprintf(stderr, "Going to perform %s\n", (char *)p.accessinfoURL); ml_timedout = FALSE; ml_start = tutil_tvnow(); while (!done) { fd_set rd, wr, exc; int max_fd; struct timeval interval; interval.tv_sec = 1; interval.tv_usec = 0; if (tutil_tvdiff(tutil_tvnow(), ml_start) > MAIN_LOOP_HANG_TIMEOUT) { ml_timedout = TRUE; break; } mp_timedout = FALSE; mp_start = tutil_tvnow(); while (res == CURLM_CALL_MULTI_PERFORM) { res = curl_multi_perform(multi, &running); if (tutil_tvdiff(tutil_tvnow(), mp_start) > MULTI_PERFORM_HANG_TIMEOUT) { mp_timedout = TRUE; break; } fprintf(stderr, "running=%d res=%d\n",running,res); if (running <= 0) { done = TRUE; break; } } if (mp_timedout || done) break; if (res != CURLM_OK) { fprintf(stderr, "not okay???\n"); i = 80; break; } FD_ZERO(&rd); FD_ZERO(&wr); FD_ZERO(&exc); max_fd = 0; if (curl_multi_fdset(multi, &rd, &wr, &exc, &max_fd) != CURLM_OK) { fprintf(stderr, "unexpected failured of fdset.\n"); i = 89; break; } if (select_test(max_fd+1, &rd, &wr, &exc, &interval) == -1) { fprintf(stderr, "bad select??\n"); i =95; break; } res = CURLM_CALL_MULTI_PERFORM; } if (ml_timedout || mp_timedout) { if (ml_timedout) fprintf(stderr, "ml_timedout\n"); if (mp_timedout) fprintf(stderr, "mp_timedout\n"); fprintf(stderr, "ABORTING TEST, since it seems " "that it would have run forever.\n"); i = TEST_ERR_RUNS_FOREVER; } else { msg = curl_multi_info_read(multi, &running); /* this should now contain a result code from the easy handle, get it */ if(msg) i = msg->data.result; fprintf(stderr, "all done\n"); } curl_multi_remove_handle(multi, p.curl); curl_easy_cleanup(p.curl); curl_multi_cleanup(multi); curl_global_cleanup(); free(p.accessinfoURL); return i; }
int RSA_verify(int dtype, unsigned char *m, unsigned int m_len, unsigned char *sigbuf, unsigned int siglen, RSA *rsa) { int i,ret=0,sigtype; unsigned char *p,*s; X509_SIG *sig=NULL; if (siglen != (unsigned int)RSA_size(rsa)) { RSAerr(RSA_F_RSA_VERIFY,RSA_R_WRONG_SIGNATURE_LENGTH); return(0); } if(rsa->flags & RSA_FLAG_SIGN_VER) return rsa->meth->rsa_verify(dtype, m, m_len, sigbuf, siglen, rsa); s=(unsigned char *)OPENSSL_malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_RSA_VERIFY,ERR_R_MALLOC_FAILURE); goto err; } if((dtype == NID_md5_sha1) && (m_len != SSL_SIG_LENGTH) ) { RSAerr(RSA_F_RSA_VERIFY,RSA_R_INVALID_MESSAGE_LENGTH); return(0); } i=RSA_public_decrypt((int)siglen,sigbuf,s,rsa,RSA_PKCS1_PADDING); if (i <= 0) goto err; /* Special case: SSL signature */ if(dtype == NID_md5_sha1) { if((i != SSL_SIG_LENGTH) || memcmp(s, m, SSL_SIG_LENGTH)) RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); else ret = 1; } else { p=s; sig=d2i_X509_SIG(NULL,&p,(long)i); if (sig == NULL) goto err; sigtype=OBJ_obj2nid(sig->algor->algorithm); #ifdef RSA_DEBUG /* put a backward compatibility flag in EAY */ fprintf(stderr,"in(%s) expect(%s)\n",OBJ_nid2ln(sigtype), OBJ_nid2ln(dtype)); #endif if (sigtype != dtype) { if (((dtype == NID_md5) && (sigtype == NID_md5WithRSAEncryption)) || ((dtype == NID_md2) && (sigtype == NID_md2WithRSAEncryption))) { /* ok, we will let it through */ #if !defined(NO_STDIO) && !defined(WIN16) fprintf(stderr,"signature has problems, re-make with post SSLeay045\n"); #endif } else { RSAerr(RSA_F_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH); goto err; } } if ( ((unsigned int)sig->digest->length != m_len) || (memcmp(m,sig->digest->data,m_len) != 0)) { RSAerr(RSA_F_RSA_VERIFY,RSA_R_BAD_SIGNATURE); } else ret=1; } err: if (sig != NULL) X509_SIG_free(sig); memset(s,0,(unsigned int)siglen); OPENSSL_free(s); return(ret); }
int test( char *URL ) { CURLM* multi; sslctxparm p; int i = 0; CURLMsg *msg; if ( arg2 ) { portnum = atoi( arg2 ); } curl_global_init( CURL_GLOBAL_ALL ); p.curl = curl_easy_init(); p.accessinfoURL = (unsigned char *) strdup( URL ); p.accesstype = OBJ_obj2nid( OBJ_txt2obj( "AD_DVCS",0 ) ) ; curl_easy_setopt( p.curl, CURLOPT_URL, p.accessinfoURL ); curl_easy_setopt( p.curl, CURLOPT_SSL_CTX_FUNCTION, sslctxfun ) ; curl_easy_setopt( p.curl, CURLOPT_SSL_CTX_DATA, &p ); curl_easy_setopt( p.curl, CURLOPT_SSL_VERIFYPEER, FALSE ); curl_easy_setopt( p.curl, CURLOPT_SSL_VERIFYHOST, 1 ); fprintf( stderr, "Going to perform %s\n", (char *)p.accessinfoURL ); { CURLMcode res; int running; char done = FALSE; multi = curl_multi_init(); res = curl_multi_add_handle( multi, p.curl ); while ( !done ) { fd_set rd, wr, exc; int max_fd; struct timeval interval; interval.tv_sec = 1; interval.tv_usec = 0; while ( res == CURLM_CALL_MULTI_PERFORM ) { res = curl_multi_perform( multi, &running ); fprintf( stderr, "running=%d res=%d\n",running,res ); if ( running <= 0 ) { done = TRUE; break; } } if ( done ) { break; } if ( res != CURLM_OK ) { fprintf( stderr, "not okay???\n" ); i = 80; break; } FD_ZERO( &rd ); FD_ZERO( &wr ); FD_ZERO( &exc ); max_fd = 0; if ( curl_multi_fdset( multi, &rd, &wr, &exc, &max_fd ) != CURLM_OK ) { fprintf( stderr, "unexpected failured of fdset.\n" ); i = 89; break; } if ( select( max_fd + 1, &rd, &wr, &exc, &interval ) == -1 ) { fprintf( stderr, "bad select??\n" ); i = 95; break; } res = CURLM_CALL_MULTI_PERFORM; } msg = curl_multi_info_read( multi, &running ); /* this should now contain a result code from the easy handle, get it */ if ( msg ) { i = msg->data.result; } } fprintf( stderr, "all done\n" ); curl_multi_remove_handle( multi, p.curl ); curl_easy_cleanup( p.curl ); curl_multi_cleanup( multi ); curl_global_cleanup(); free( p.accessinfoURL ); return i; }
/* FIXME: Master-Key, Extensions, CA bits (openssl x509 -text -in servcert.pem) */ int _SSL_get_cert_info (struct cert_info *cert_info, SSL * ssl) { X509 *peer_cert; EVP_PKEY *peer_pkey; /* EVP_PKEY *ca_pkey; */ /* EVP_PKEY *tmp_pkey; */ char notBefore[64]; char notAfter[64]; int alg; int sign_alg; if (!(peer_cert = SSL_get_peer_certificate (ssl))) return (1); /* FATAL? */ X509_NAME_oneline (X509_get_subject_name (peer_cert), cert_info->subject, sizeof (cert_info->subject)); X509_NAME_oneline (X509_get_issuer_name (peer_cert), cert_info->issuer, sizeof (cert_info->issuer)); broke_oneline (cert_info->subject, cert_info->subject_word); broke_oneline (cert_info->issuer, cert_info->issuer_word); alg = OBJ_obj2nid (peer_cert->cert_info->key->algor->algorithm); sign_alg = OBJ_obj2nid (peer_cert->sig_alg->algorithm); ASN1_TIME_snprintf (notBefore, sizeof (notBefore), X509_get_notBefore (peer_cert)); ASN1_TIME_snprintf (notAfter, sizeof (notAfter), X509_get_notAfter (peer_cert)); peer_pkey = X509_get_pubkey (peer_cert); strncpy (cert_info->algorithm, (alg == NID_undef) ? "Unknown" : OBJ_nid2ln (alg), sizeof (cert_info->algorithm)); cert_info->algorithm_bits = EVP_PKEY_bits (peer_pkey); strncpy (cert_info->sign_algorithm, (sign_alg == NID_undef) ? "Unknown" : OBJ_nid2ln (sign_alg), sizeof (cert_info->sign_algorithm)); /* EVP_PKEY_bits(ca_pkey)); */ cert_info->sign_algorithm_bits = 0; strncpy (cert_info->notbefore, notBefore, sizeof (cert_info->notbefore)); strncpy (cert_info->notafter, notAfter, sizeof (cert_info->notafter)); EVP_PKEY_free (peer_pkey); /* SSL_SESSION_print_fp(stdout, SSL_get_session(ssl)); */ /* if (ssl->session->sess_cert->peer_rsa_tmp) { tmp_pkey = EVP_PKEY_new(); EVP_PKEY_assign_RSA(tmp_pkey, ssl->session->sess_cert->peer_rsa_tmp); cert_info->rsa_tmp_bits = EVP_PKEY_bits (tmp_pkey); EVP_PKEY_free(tmp_pkey); } else fprintf(stderr, "REMOTE SIDE DOESN'T PROVIDES ->peer_rsa_tmp\n"); */ cert_info->rsa_tmp_bits = 0; X509_free (peer_cert); return (0); }
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a, ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey) { EVP_MD_CTX ctx; unsigned char *buf_in=NULL; int ret= -1,inl; int mdnid, pknid; if (!pkey) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY, ERR_R_PASSED_NULL_PARAMETER); return -1; } EVP_MD_CTX_init(&ctx); /* Convert signature OID into digest and public key OIDs */ if (!OBJ_find_sigid_algs(OBJ_obj2nid(a->algorithm), &mdnid, &pknid)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); goto err; } if (mdnid == NID_undef) { if (!pkey->ameth || !pkey->ameth->item_verify) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_SIGNATURE_ALGORITHM); goto err; } ret = pkey->ameth->item_verify(&ctx, it, asn, a, signature, pkey); /* Return value of 2 means carry on, anything else means we * exit straight away: either a fatal error of the underlying * verification routine handles all verification. */ if (ret != 2) goto err; ret = -1; } else { const EVP_MD *type; type=EVP_get_digestbynid(mdnid); if (type == NULL) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM); goto err; } /* Check public key OID matches public key type */ if (EVP_PKEY_type(pknid) != pkey->ameth->pkey_id) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ASN1_R_WRONG_PUBLIC_KEY_TYPE); goto err; } if (!EVP_DigestVerifyInit(&ctx, NULL, type, NULL, pkey)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; goto err; } } inl = ASN1_item_i2d(asn, &buf_in, it); if (buf_in == NULL) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_MALLOC_FAILURE); goto err; } if (!EVP_DigestVerifyUpdate(&ctx,buf_in,inl)) { ASN1err(ASN1_F_ASN1_ITEM_VERIFY,ERR_R_EVP_LIB); ret=0; goto err; } OPENSSL_cleanse(buf_in,(unsigned int)inl); OPENSSL_free(buf_in); if (EVP_DigestVerifyFinal(&ctx,signature->data, (size_t)signature->length) <= 0) { ASN1err(ASN1_F_ASN1_ITEM_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: EVP_MD_CTX_cleanup(&ctx); return(ret); }
EVP_PKEY *X509_PUBKEY_get(X509_PUBKEY *key) { EVP_PKEY *ret=NULL; if (key == NULL) goto error; if (key->pkey != NULL) { CRYPTO_add(&key->pkey->references, 1, CRYPTO_LOCK_EVP_PKEY); return key->pkey; } if (key->public_key == NULL) goto error; if ((ret = EVP_PKEY_new()) == NULL) { X509err(X509_F_X509_PUBKEY_GET, ERR_R_MALLOC_FAILURE); goto error; } if (!EVP_PKEY_set_type(ret, OBJ_obj2nid(key->algor->algorithm))) { X509err(X509_F_X509_PUBKEY_GET,X509_R_UNSUPPORTED_ALGORITHM); goto error; } if (ret->ameth->pub_decode) { if (!ret->ameth->pub_decode(ret, key)) { X509err(X509_F_X509_PUBKEY_GET, X509_R_PUBLIC_KEY_DECODE_ERROR); goto error; } } else { X509err(X509_F_X509_PUBKEY_GET, X509_R_METHOD_NOT_SUPPORTED); goto error; } /* Check to see if another thread set key->pkey first */ CRYPTO_w_lock(CRYPTO_LOCK_EVP_PKEY); if (key->pkey) { CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); EVP_PKEY_free(ret); ret = key->pkey; } else { key->pkey = ret; CRYPTO_w_unlock(CRYPTO_LOCK_EVP_PKEY); } CRYPTO_add(&ret->references, 1, CRYPTO_LOCK_EVP_PKEY); return ret; error: if (ret != NULL) EVP_PKEY_free(ret); return(NULL); }
static int do_name_ex(char_io *io_ch, void *arg, X509_NAME *n, int indent, unsigned long flags) { int i, prev = -1, orflags, cnt; int fn_opt, fn_nid; ASN1_OBJECT *fn; ASN1_STRING *val; X509_NAME_ENTRY *ent; char objtmp[80]; const char *objbuf; int outlen, len; char *sep_dn, *sep_mv, *sep_eq; int sep_dn_len, sep_mv_len, sep_eq_len; if(indent < 0) indent = 0; outlen = indent; if(!do_indent(io_ch, arg, indent)) return -1; switch (flags & XN_FLAG_SEP_MASK) { case XN_FLAG_SEP_MULTILINE: sep_dn = "\n"; sep_dn_len = 1; sep_mv = " + "; sep_mv_len = 3; break; case XN_FLAG_SEP_COMMA_PLUS: sep_dn = ","; sep_dn_len = 1; sep_mv = "+"; sep_mv_len = 1; indent = 0; break; case XN_FLAG_SEP_CPLUS_SPC: sep_dn = ", "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; case XN_FLAG_SEP_SPLUS_SPC: sep_dn = "; "; sep_dn_len = 2; sep_mv = " + "; sep_mv_len = 3; indent = 0; break; default: return -1; } if(flags & XN_FLAG_SPC_EQ) { sep_eq = " = "; sep_eq_len = 3; } else { sep_eq = "="; sep_eq_len = 1; } fn_opt = flags & XN_FLAG_FN_MASK; cnt = X509_NAME_entry_count(n); for(i = 0; i < cnt; i++) { if(flags & XN_FLAG_DN_REV) ent = X509_NAME_get_entry(n, cnt - i - 1); else ent = X509_NAME_get_entry(n, i); if(prev != -1) { if(prev == ent->set) { if(!io_ch(arg, sep_mv, sep_mv_len)) return -1; outlen += sep_mv_len; } else { if(!io_ch(arg, sep_dn, sep_dn_len)) return -1; outlen += sep_dn_len; if(!do_indent(io_ch, arg, indent)) return -1; outlen += indent; } } prev = ent->set; fn = X509_NAME_ENTRY_get_object(ent); val = X509_NAME_ENTRY_get_data(ent); fn_nid = OBJ_obj2nid(fn); if(fn_opt != XN_FLAG_FN_NONE) { int objlen, fld_len; if((fn_opt == XN_FLAG_FN_OID) || (fn_nid==NID_undef) ) { OBJ_obj2txt(objtmp, sizeof objtmp, fn, 1); fld_len = 0; /* XXX: what should this be? */ objbuf = objtmp; } else { if(fn_opt == XN_FLAG_FN_SN) { fld_len = FN_WIDTH_SN; objbuf = OBJ_nid2sn(fn_nid); } else if(fn_opt == XN_FLAG_FN_LN) { fld_len = FN_WIDTH_LN; objbuf = OBJ_nid2ln(fn_nid); } else { fld_len = 0; /* XXX: what should this be? */ objbuf = ""; } } objlen = strlen(objbuf); if(!io_ch(arg, objbuf, objlen)) return -1; if ((objlen < fld_len) && (flags & XN_FLAG_FN_ALIGN)) { if (!do_indent(io_ch, arg, fld_len - objlen)) return -1; outlen += fld_len - objlen; } if(!io_ch(arg, sep_eq, sep_eq_len)) return -1; outlen += objlen + sep_eq_len; } /* If the field name is unknown then fix up the DER dump * flag. We might want to limit this further so it will * DER dump on anything other than a few 'standard' fields. */ if((fn_nid == NID_undef) && (flags & XN_FLAG_DUMP_UNKNOWN_FIELDS)) orflags = ASN1_STRFLGS_DUMP_ALL; else orflags = 0; len = do_print_ex(io_ch, arg, flags | orflags, val); if(len < 0) return -1; outlen += len; } return outlen; }
int pkcs7_main(int argc, char **argv) { PKCS7 *p7 = NULL; BIO *in = NULL, *out = NULL; int informat = FORMAT_PEM, outformat = FORMAT_PEM; char *infile = NULL, *outfile = NULL, *prog; int i, print_certs = 0, text = 0, noout = 0, p7_print = 0, ret = 1; OPTION_CHOICE o; prog = opt_init(argc, argv, pkcs7_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { case OPT_EOF: case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); goto end; case OPT_HELP: opt_help(pkcs7_options); ret = 0; goto end; case OPT_INFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &informat)) goto opthelp; break; case OPT_OUTFORM: if (!opt_format(opt_arg(), OPT_FMT_PEMDER, &outformat)) goto opthelp; break; case OPT_IN: infile = opt_arg(); break; case OPT_OUT: outfile = opt_arg(); break; case OPT_NOOUT: noout = 1; break; case OPT_TEXT: text = 1; break; case OPT_PRINT: p7_print = 1; break; case OPT_PRINT_CERTS: print_certs = 1; break; case OPT_ENGINE: (void)setup_engine(opt_arg(), 0); break; } } argc = opt_num_rest(); if (argc != 0) goto opthelp; in = bio_open_default(infile, 'r', informat); if (in == NULL) goto end; if (informat == FORMAT_ASN1) p7 = d2i_PKCS7_bio(in, NULL); else p7 = PEM_read_bio_PKCS7(in, NULL, NULL, NULL); if (p7 == NULL) { BIO_printf(bio_err, "unable to load PKCS7 object\n"); ERR_print_errors(bio_err); goto end; } out = bio_open_default(outfile, 'w', outformat); if (out == NULL) goto end; if (p7_print) PKCS7_print_ctx(out, p7, 0, NULL); if (print_certs) { STACK_OF(X509) *certs = NULL; STACK_OF(X509_CRL) *crls = NULL; i = OBJ_obj2nid(p7->type); switch (i) { case NID_pkcs7_signed: if (p7->d.sign != NULL) { certs = p7->d.sign->cert; crls = p7->d.sign->crl; } break; case NID_pkcs7_signedAndEnveloped: if (p7->d.signed_and_enveloped != NULL) { certs = p7->d.signed_and_enveloped->cert; crls = p7->d.signed_and_enveloped->crl; } break; default: break; } if (certs != NULL) { X509 *x; for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); if (text) X509_print(out, x); else dump_cert_text(out, x); if (!noout) PEM_write_bio_X509(out, x); BIO_puts(out, "\n"); } } if (crls != NULL) { X509_CRL *crl; for (i = 0; i < sk_X509_CRL_num(crls); i++) { crl = sk_X509_CRL_value(crls, i); X509_CRL_print(out, crl); if (!noout) PEM_write_bio_X509_CRL(out, crl); BIO_puts(out, "\n"); } } ret = 0; goto end; } if (!noout) { if (outformat == FORMAT_ASN1) i = i2d_PKCS7_bio(out, p7); else i = PEM_write_bio_PKCS7(out, p7); if (!i) { BIO_printf(bio_err, "unable to write pkcs7 object\n"); ERR_print_errors(bio_err); goto end; } } ret = 0; end: PKCS7_free(p7); BIO_free(in); BIO_free_all(out); return (ret); }
static int crl_set_issuers(X509_CRL *crl) { int i, j; GENERAL_NAMES *gens, *gtmp; STACK_OF(X509_REVOKED) *revoked; revoked = X509_CRL_get_REVOKED(crl); gens = NULL; for (i = 0; i < sk_X509_REVOKED_num(revoked); i++) { X509_REVOKED *rev = sk_X509_REVOKED_value(revoked, i); STACK_OF(X509_EXTENSION) *exts; ASN1_ENUMERATED *reason; X509_EXTENSION *ext; gtmp = X509_REVOKED_get_ext_d2i(rev, NID_certificate_issuer, &j, NULL); if (!gtmp && (j != -1)) { crl->flags |= EXFLAG_INVALID; return 1; } if (gtmp) { gens = gtmp; if (!crl->issuers) { crl->issuers = sk_GENERAL_NAMES_new_null(); if (!crl->issuers) return 0; } if (!sk_GENERAL_NAMES_push(crl->issuers, gtmp)) return 0; } rev->issuer = gens; reason = X509_REVOKED_get_ext_d2i(rev, NID_crl_reason, &j, NULL); if (!reason && (j != -1)) { crl->flags |= EXFLAG_INVALID; return 1; } if (reason) { rev->reason = ASN1_ENUMERATED_get(reason); ASN1_ENUMERATED_free(reason); } else rev->reason = CRL_REASON_NONE; /* Check for critical CRL entry extensions */ exts = rev->extensions; for (j = 0; j < sk_X509_EXTENSION_num(exts); j++) { ext = sk_X509_EXTENSION_value(exts, j); if (ext->critical > 0) { if (OBJ_obj2nid(ext->object) == NID_certificate_issuer) continue; crl->flags |= EXFLAG_CRITICAL; break; } } } return 1; }
char *X509_NAME_oneline(X509_NAME *a, char *buf, int len) { X509_NAME_ENTRY *ne; size_t i; int n, lold, l, l1, l2, num, j, type; const char *s; char *p; unsigned char *q; BUF_MEM *b = NULL; static const char hex[17] = "0123456789ABCDEF"; int gs_doit[4]; char tmp_buf[80]; if (buf == NULL) { if ((b = BUF_MEM_new()) == NULL) goto err; if (!BUF_MEM_grow(b, 200)) goto err; b->data[0] = '\0'; len = 200; } else if (len <= 0) { return NULL; } if (a == NULL) { if (b) { buf = b->data; OPENSSL_free(b); } strncpy(buf, "NO X509_NAME", len); buf[len - 1] = '\0'; return buf; } len--; /* space for '\0' */ l = 0; for (i = 0; i < sk_X509_NAME_ENTRY_num(a->entries); i++) { ne = sk_X509_NAME_ENTRY_value(a->entries, i); n = OBJ_obj2nid(ne->object); if ((n == NID_undef) || ((s = OBJ_nid2sn(n)) == NULL)) { i2t_ASN1_OBJECT(tmp_buf, sizeof(tmp_buf), ne->object); s = tmp_buf; } l1 = strlen(s); type = ne->value->type; num = ne->value->length; if (num > NAME_ONELINE_MAX) { OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); goto end; } q = ne->value->data; if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) { gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 0; for (j = 0; j < num; j++) if (q[j] != 0) gs_doit[j & 3] = 1; if (gs_doit[0] | gs_doit[1] | gs_doit[2]) gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; else { gs_doit[0] = gs_doit[1] = gs_doit[2] = 0; gs_doit[3] = 1; } } else gs_doit[0] = gs_doit[1] = gs_doit[2] = gs_doit[3] = 1; for (l2 = j = 0; j < num; j++) { if (!gs_doit[j & 3]) continue; l2++; if ((q[j] < ' ') || (q[j] > '~')) l2 += 3; } lold = l; l += 1 + l1 + 1 + l2; if (l > NAME_ONELINE_MAX) { OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG); goto end; } if (b != NULL) { if (!BUF_MEM_grow(b, l + 1)) goto err; p = &(b->data[lold]); } else if (l > len) { break; } else p = &(buf[lold]); *(p++) = '/'; OPENSSL_memcpy(p, s, (unsigned int)l1); p += l1; *(p++) = '='; q = ne->value->data; for (j = 0; j < num; j++) { if (!gs_doit[j & 3]) continue; n = q[j]; if ((n < ' ') || (n > '~')) { *(p++) = '\\'; *(p++) = 'x'; *(p++) = hex[(n >> 4) & 0x0f]; *(p++) = hex[n & 0x0f]; } else *(p++) = n; }
/* The X509_CRL structure needs a bit of customisation. Cache some extensions * and hash of the whole CRL. */ static int crl_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg) { X509_CRL *crl = (X509_CRL *)*pval; STACK_OF(X509_EXTENSION) *exts; X509_EXTENSION *ext; int idx; switch (operation) { case ASN1_OP_NEW_POST: crl->idp = NULL; crl->akid = NULL; crl->flags = 0; crl->idp_flags = 0; crl->idp_reasons = CRLDP_ALL_REASONS; crl->meth = default_crl_method; crl->meth_data = NULL; crl->issuers = NULL; crl->crl_number = NULL; crl->base_crl_number = NULL; break; case ASN1_OP_D2I_POST: #ifndef OPENSSL_NO_SHA X509_CRL_digest(crl, EVP_sha1(), crl->sha1_hash, NULL); #endif crl->idp = X509_CRL_get_ext_d2i(crl, NID_issuing_distribution_point, NULL, NULL); if (crl->idp) setup_idp(crl, crl->idp); crl->akid = X509_CRL_get_ext_d2i(crl, NID_authority_key_identifier, NULL, NULL); crl->crl_number = X509_CRL_get_ext_d2i(crl, NID_crl_number, NULL, NULL); crl->base_crl_number = X509_CRL_get_ext_d2i(crl, NID_delta_crl, NULL, NULL); /* Delta CRLs must have CRL number */ if (crl->base_crl_number && !crl->crl_number) crl->flags |= EXFLAG_INVALID; /* See if we have any unhandled critical CRL extensions and * indicate this in a flag. We only currently handle IDP, * AKID and deltas, so anything else critical sets the flag. * * This code accesses the X509_CRL structure directly: * applications shouldn't do this. */ exts = crl->crl->extensions; for (idx = 0; idx < sk_X509_EXTENSION_num(exts); idx++) { int nid; ext = sk_X509_EXTENSION_value(exts, idx); nid = OBJ_obj2nid(ext->object); if (nid == NID_freshest_crl) crl->flags |= EXFLAG_FRESHEST; if (ext->critical > 0) { /* We handle IDP, AKID and deltas */ if (nid == NID_issuing_distribution_point || nid == NID_authority_key_identifier || nid == NID_delta_crl) break; crl->flags |= EXFLAG_CRITICAL; break; } } if (!crl_set_issuers(crl)) return 0; if (crl->meth->crl_init) { if (crl->meth->crl_init(crl) == 0) return 0; } break; case ASN1_OP_FREE_POST: if (crl->meth->crl_free) { if (!crl->meth->crl_free(crl)) return 0; } if (crl->akid) AUTHORITY_KEYID_free(crl->akid); if (crl->idp) ISSUING_DIST_POINT_free(crl->idp); ASN1_INTEGER_free(crl->crl_number); ASN1_INTEGER_free(crl->base_crl_number); sk_GENERAL_NAMES_pop_free(crl->issuers, GENERAL_NAMES_free); break; } return 1; }
BIO *PKCS7_dataInit(PKCS7 *p7, BIO *bio) { int i,j; BIO *out=NULL,*btmp=NULL; X509_ALGOR *xa; const EVP_MD *evp_md; const EVP_CIPHER *evp_cipher=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; EVP_PKEY *pkey; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: md_sk=p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; xalg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=p7->d.signed_and_enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; xalg=p7->d.enveloped->enc_data->algorithm; evp_cipher=p7->d.enveloped->enc_data->cipher; if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT, PKCS7_R_CIPHER_NOT_INITIALIZED); goto err; } break; default: PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } if (md_sk != NULL) { for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) { xa=sk_X509_ALGOR_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } j=OBJ_obj2nid(xa->algorithm); evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } BIO_set_md(btmp,evp_md); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } } if (evp_cipher != NULL) { unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; int keylen,ivlen; int jj,max; unsigned char *tmp; EVP_CIPHER_CTX *ctx; if ((btmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_BIO_LIB); goto err; } BIO_get_cipher_ctx(btmp, &ctx); keylen=EVP_CIPHER_key_length(evp_cipher); ivlen=EVP_CIPHER_iv_length(evp_cipher); if (RAND_bytes(key,keylen) <= 0) goto err; xalg->algorithm = OBJ_nid2obj(EVP_CIPHER_type(evp_cipher)); if (ivlen > 0) RAND_pseudo_bytes(iv,ivlen); EVP_CipherInit_ex(ctx, evp_cipher, NULL, key, iv, 1); if (ivlen > 0) { if (xalg->parameter == NULL) xalg->parameter=ASN1_TYPE_new(); if(EVP_CIPHER_param_to_asn1(ctx, xalg->parameter) < 0) goto err; } /* Lets do the pub key stuff :-) */ max=0; for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if (ri->cert == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,PKCS7_R_MISSING_CERIPEND_INFO); goto err; } pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_size(pkey); EVP_PKEY_free(pkey); if (max < jj) max=jj; } if ((tmp=(unsigned char *)OPENSSL_malloc(max)) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_MALLOC_FAILURE); goto err; } for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); pkey=X509_get_pubkey(ri->cert); jj=EVP_PKEY_encrypt(tmp,key,keylen,pkey); EVP_PKEY_free(pkey); if (jj <= 0) { PKCS7err(PKCS7_F_PKCS7_DATAINIT,ERR_R_EVP_LIB); OPENSSL_free(tmp); goto err; } M_ASN1_OCTET_STRING_set(ri->enc_key,tmp,jj); } OPENSSL_free(tmp); OPENSSL_cleanse(key, keylen); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } if (bio == NULL) { if (PKCS7_is_detached(p7)) bio=BIO_new(BIO_s_null()); else { if (PKCS7_type_is_signed(p7) ) { if ( PKCS7_type_is_data(p7->d.sign->contents)) { ASN1_OCTET_STRING *os; os=p7->d.sign->contents->d.data; if (os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); } else if ( PKCS7_type_is_octet_string(p7->d.sign->contents) ) { ASN1_OCTET_STRING *os; os=p7->d.sign->contents->d.other->value.octet_string; if (os->length > 0) bio = BIO_new_mem_buf(os->data, os->length); } } if(bio == NULL) { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } } } BIO_push(out,bio); bio=NULL; if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); out=NULL; } return(out); }
int X509_REQ_print_ex(BIO *bp, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { unsigned long l; int i; const char *neg; X509_REQ_INFO *ri; EVP_PKEY *pkey; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(X509_EXTENSION) *exts; char mlch = ' '; int nmindent = 0; if((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if(nmflags == X509_FLAG_COMPAT) nmindent = 16; ri=x->req_info; if(!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bp,"Certificate Request:\n",21) <= 0) goto err; if (BIO_write(bp," Data:\n",10) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_VERSION)) { neg=(ri->version->type == V_ASN1_NEG_INTEGER)?"-":""; l=0; for (i=0; i<ri->version->length; i++) { l<<=8; l+=ri->version->data[i]; } if(BIO_printf(bp,"%8sVersion: %s%lu (%s0x%lx)\n","",neg,l,neg, l) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bp," Subject:%c",mlch) <= 0) goto err; if (X509_NAME_print_ex(bp,ri->subject,nmindent, nmflags) < 0) goto err; if (BIO_write(bp,"\n",1) <= 0) goto err; } if(!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bp," Subject Public Key Info:\n",33) <= 0) goto err; if (BIO_printf(bp,"%12sPublic Key Algorithm: ","") <= 0) goto err; if (i2a_ASN1_OBJECT(bp, ri->pubkey->algor->algorithm) <= 0) goto err; if (BIO_puts(bp, "\n") <= 0) goto err; pkey=X509_REQ_get_pubkey(x); if (pkey == NULL) { BIO_printf(bp,"%12sUnable to load Public Key\n",""); ERR_print_errors(bp); } else #ifndef OPENSSL_NO_RSA if (pkey->type == EVP_PKEY_RSA) { BIO_printf(bp,"%12sRSA Public Key: (%d bit)\n","", BN_num_bits(pkey->pkey.rsa->n)); RSA_print(bp,pkey->pkey.rsa,16); } else #endif #ifndef OPENSSL_NO_DSA if (pkey->type == EVP_PKEY_DSA) { BIO_printf(bp,"%12sDSA Public Key:\n",""); DSA_print(bp,pkey->pkey.dsa,16); } else #endif BIO_printf(bp,"%12sUnknown Public Key:\n",""); EVP_PKEY_free(pkey); } if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) { /* may not be */ if(BIO_printf(bp,"%8sAttributes:\n","") <= 0) goto err; sk=x->req_info->attributes; if (sk_X509_ATTRIBUTE_num(sk) == 0) { if(BIO_printf(bp,"%12sa0:00\n","") <= 0) goto err; } else { for (i=0; i<sk_X509_ATTRIBUTE_num(sk); i++) { ASN1_TYPE *at; X509_ATTRIBUTE *a; ASN1_BIT_STRING *bs=NULL; ASN1_TYPE *t; int j,type=0,count=1,ii=0; a=sk_X509_ATTRIBUTE_value(sk,i); if(X509_REQ_extension_nid(OBJ_obj2nid(a->object))) continue; if(BIO_printf(bp,"%12s","") <= 0) goto err; if ((j=i2a_ASN1_OBJECT(bp,a->object)) > 0) { if (a->single) { t=a->value.single; type=t->type; bs=t->value.bit_string; } else { ii=0; count=sk_ASN1_TYPE_num(a->value.set); get_next: at=sk_ASN1_TYPE_value(a->value.set,ii); type=at->type; bs=at->value.asn1_string; } } for (j=25-j; j>0; j--) if (BIO_write(bp," ",1) != 1) goto err; if (BIO_puts(bp,":") <= 0) goto err; if ( (type == V_ASN1_PRINTABLESTRING) || (type == V_ASN1_T61STRING) || (type == V_ASN1_IA5STRING)) { if (BIO_write(bp,(char *)bs->data,bs->length) != bs->length) goto err; BIO_puts(bp,"\n"); } else { BIO_puts(bp,"unable to print attribute\n"); } if (++ii < count) goto get_next; } } } if(!(cflag & X509_FLAG_NO_ATTRIBUTES)) { exts = X509_REQ_get_extensions(x); if(exts) { BIO_printf(bp,"%8sRequested Extensions:\n",""); for (i=0; i<sk_X509_EXTENSION_num(exts); i++) { ASN1_OBJECT *obj; X509_EXTENSION *ex; int j; ex=sk_X509_EXTENSION_value(exts, i); if (BIO_printf(bp,"%12s","") <= 0) goto err; obj=X509_EXTENSION_get_object(ex); i2a_ASN1_OBJECT(bp,obj); j=X509_EXTENSION_get_critical(ex); if (BIO_printf(bp,": %s\n",j?"critical":"","") <= 0) goto err; if(!X509V3_EXT_print(bp, ex, 0, 16)) { BIO_printf(bp, "%16s", ""); M_ASN1_OCTET_STRING_print(bp,ex->value); } if (BIO_write(bp,"\n",1) <= 0) goto err; } sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } if(!(cflag & X509_FLAG_NO_SIGDUMP)) { if(!X509_signature_print(bp, x->sig_alg, x->signature)) goto err; } return(1); err: X509err(X509_F_X509_REQ_PRINT,ERR_R_BUF_LIB); return(0); }
/* int */ BIO *PKCS7_dataDecode(PKCS7 *p7, EVP_PKEY *pkey, BIO *in_bio, X509 *pcert) { int i,j; BIO *out=NULL,*btmp=NULL,*etmp=NULL,*bio=NULL; unsigned char *tmp=NULL; X509_ALGOR *xa; ASN1_OCTET_STRING *data_body=NULL; const EVP_MD *evp_md; const EVP_CIPHER *evp_cipher=NULL; EVP_CIPHER_CTX *evp_ctx=NULL; X509_ALGOR *enc_alg=NULL; STACK_OF(X509_ALGOR) *md_sk=NULL; STACK_OF(PKCS7_RECIP_INFO) *rsk=NULL; X509_ALGOR *xalg=NULL; PKCS7_RECIP_INFO *ri=NULL; i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signed: data_body=p7->d.sign->contents->d.data; md_sk=p7->d.sign->md_algs; break; case NID_pkcs7_signedAndEnveloped: rsk=p7->d.signed_and_enveloped->recipientinfo; md_sk=p7->d.signed_and_enveloped->md_algs; data_body=p7->d.signed_and_enveloped->enc_data->enc_data; enc_alg=p7->d.signed_and_enveloped->enc_data->algorithm; evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.signed_and_enveloped->enc_data->algorithm; break; case NID_pkcs7_enveloped: rsk=p7->d.enveloped->recipientinfo; enc_alg=p7->d.enveloped->enc_data->algorithm; data_body=p7->d.enveloped->enc_data->enc_data; evp_cipher=EVP_get_cipherbyname(OBJ_nid2sn(OBJ_obj2nid(enc_alg->algorithm))); if (evp_cipher == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CIPHER_TYPE); goto err; } xalg=p7->d.enveloped->enc_data->algorithm; break; default: PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNSUPPORTED_CONTENT_TYPE); goto err; } /* We will be checking the signature */ if (md_sk != NULL) { for (i=0; i<sk_X509_ALGOR_num(md_sk); i++) { xa=sk_X509_ALGOR_value(md_sk,i); if ((btmp=BIO_new(BIO_f_md())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } j=OBJ_obj2nid(xa->algorithm); evp_md=EVP_get_digestbyname(OBJ_nid2sn(j)); if (evp_md == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,PKCS7_R_UNKNOWN_DIGEST_TYPE); goto err; } BIO_set_md(btmp,evp_md); if (out == NULL) out=btmp; else BIO_push(out,btmp); btmp=NULL; } } if (evp_cipher != NULL) { #if 0 unsigned char key[EVP_MAX_KEY_LENGTH]; unsigned char iv[EVP_MAX_IV_LENGTH]; unsigned char *p; int keylen,ivlen; int max; X509_OBJECT ret; #endif int jj; if ((etmp=BIO_new(BIO_f_cipher())) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_BIO_LIB); goto err; } /* It was encrypted, we need to decrypt the secret key * with the private key */ /* Find the recipientInfo which matches the passed certificate * (if any) */ for (i=0; i<sk_PKCS7_RECIP_INFO_num(rsk); i++) { ri=sk_PKCS7_RECIP_INFO_value(rsk,i); if(!X509_NAME_cmp(ri->issuer_and_serial->issuer, pcert->cert_info->issuer) && !M_ASN1_INTEGER_cmp(pcert->cert_info->serialNumber, ri->issuer_and_serial->serial)) break; ri=NULL; } if (ri == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_NO_RECIPIENT_MATCHES_CERTIFICATE); goto err; } jj=EVP_PKEY_size(pkey); tmp=(unsigned char *)OPENSSL_malloc(jj+10); if (tmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_MALLOC_FAILURE); goto err; } jj=EVP_PKEY_decrypt(tmp, M_ASN1_STRING_data(ri->enc_key), M_ASN1_STRING_length(ri->enc_key), pkey); if (jj <= 0) { PKCS7err(PKCS7_F_PKCS7_DATADECODE,ERR_R_EVP_LIB); goto err; } evp_ctx=NULL; BIO_get_cipher_ctx(etmp,&evp_ctx); EVP_CipherInit_ex(evp_ctx,evp_cipher,NULL,NULL,NULL,0); if (EVP_CIPHER_asn1_to_param(evp_ctx,enc_alg->parameter) < 0) goto err; if (jj != EVP_CIPHER_CTX_key_length(evp_ctx)) { /* Some S/MIME clients don't use the same key * and effective key length. The key length is * determined by the size of the decrypted RSA key. */ if(!EVP_CIPHER_CTX_set_key_length(evp_ctx, jj)) { PKCS7err(PKCS7_F_PKCS7_DATADECODE, PKCS7_R_DECRYPTED_KEY_IS_WRONG_LENGTH); goto err; } } EVP_CipherInit_ex(evp_ctx,NULL,NULL,tmp,NULL,0); OPENSSL_cleanse(tmp,jj); if (out == NULL) out=etmp; else BIO_push(out,etmp); etmp=NULL; } #if 1 if (PKCS7_is_detached(p7) || (in_bio != NULL)) { bio=in_bio; } else { #if 0 bio=BIO_new(BIO_s_mem()); /* We need to set this so that when we have read all * the data, the encrypt BIO, if present, will read * EOF and encode the last few bytes */ BIO_set_mem_eof_return(bio,0); if (data_body->length > 0) BIO_write(bio,(char *)data_body->data,data_body->length); #else if (data_body->length > 0) bio = BIO_new_mem_buf(data_body->data,data_body->length); else { bio=BIO_new(BIO_s_mem()); BIO_set_mem_eof_return(bio,0); } #endif } BIO_push(out,bio); bio=NULL; #endif if (0) { err: if (out != NULL) BIO_free_all(out); if (btmp != NULL) BIO_free_all(btmp); if (etmp != NULL) BIO_free_all(etmp); if (bio != NULL) BIO_free_all(bio); out=NULL; } if (tmp != NULL) OPENSSL_free(tmp); return(out); }
static int newpass_p12(PKCS12 *p12, char *oldpass, char *newpass) { STACK_OF(PKCS7) *asafes, *newsafes; STACK_OF(PKCS12_SAFEBAG) *bags; int i, bagnid, pbe_nid = 0, pbe_iter = 0, pbe_saltlen = 0; PKCS7 *p7, *p7new; ASN1_OCTET_STRING *p12_data_tmp = NULL, *macnew = NULL; unsigned char mac[EVP_MAX_MD_SIZE]; unsigned int maclen; if (!(asafes = PKCS12_unpack_authsafes(p12))) return 0; if(!(newsafes = sk_PKCS7_new_null())) return 0; for (i = 0; i < sk_PKCS7_num (asafes); i++) { p7 = sk_PKCS7_value(asafes, i); bagnid = OBJ_obj2nid(p7->type); if (bagnid == NID_pkcs7_data) { bags = PKCS12_unpack_p7data(p7); } else if (bagnid == NID_pkcs7_encrypted) { bags = PKCS12_unpack_p7encdata(p7, oldpass, -1); alg_get(p7->d.encrypted->enc_data->algorithm, &pbe_nid, &pbe_iter, &pbe_saltlen); } else continue; if (!bags) { sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } if (!newpass_bags(bags, oldpass, newpass)) { sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } /* Repack bag in same form with new password */ if (bagnid == NID_pkcs7_data) p7new = PKCS12_pack_p7data(bags); else p7new = PKCS12_pack_p7encdata(pbe_nid, newpass, -1, NULL, pbe_saltlen, pbe_iter, bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); if(!p7new) { sk_PKCS7_pop_free(asafes, PKCS7_free); return 0; } sk_PKCS7_push(newsafes, p7new); } sk_PKCS7_pop_free(asafes, PKCS7_free); /* Repack safe: save old safe in case of error */ p12_data_tmp = p12->authsafes->d.data; if(!(p12->authsafes->d.data = ASN1_OCTET_STRING_new())) goto saferr; if(!PKCS12_pack_authsafes(p12, newsafes)) goto saferr; if(!PKCS12_gen_mac(p12, newpass, -1, mac, &maclen)) goto saferr; if(!(macnew = ASN1_OCTET_STRING_new())) goto saferr; if(!ASN1_OCTET_STRING_set(macnew, mac, maclen)) goto saferr; ASN1_OCTET_STRING_free(p12->mac->dinfo->digest); p12->mac->dinfo->digest = macnew; ASN1_OCTET_STRING_free(p12_data_tmp); return 1; saferr: /* Restore old safe */ ASN1_OCTET_STRING_free(p12->authsafes->d.data); ASN1_OCTET_STRING_free(macnew); p12->authsafes->d.data = p12_data_tmp; return 0; }
int PKCS7_dataFinal(PKCS7 *p7, BIO *bio) { int ret=0; int i,j; BIO *btmp; BUF_MEM *buf_mem=NULL; BUF_MEM *buf=NULL; PKCS7_SIGNER_INFO *si; EVP_MD_CTX *mdc,ctx_tmp; STACK_OF(X509_ATTRIBUTE) *sk; STACK_OF(PKCS7_SIGNER_INFO) *si_sk=NULL; ASN1_OCTET_STRING *os=NULL; EVP_MD_CTX_init(&ctx_tmp); i=OBJ_obj2nid(p7->type); p7->state=PKCS7_S_HEADER; switch (i) { case NID_pkcs7_signedAndEnveloped: /* XXXXXXXXXXXXXXXX */ si_sk=p7->d.signed_and_enveloped->signer_info; os=M_ASN1_OCTET_STRING_new(); p7->d.signed_and_enveloped->enc_data->enc_data=os; break; case NID_pkcs7_enveloped: /* XXXXXXXXXXXXXXXX */ os=M_ASN1_OCTET_STRING_new(); p7->d.enveloped->enc_data->enc_data=os; break; case NID_pkcs7_signed: si_sk=p7->d.sign->signer_info; os=p7->d.sign->contents->d.data; /* If detached data then the content is excluded */ if(p7->detached) { M_ASN1_OCTET_STRING_free(os); p7->d.sign->contents->d.data = NULL; } break; } if (si_sk != NULL) { if ((buf=BUF_MEM_new()) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); goto err; } for (i=0; i<sk_PKCS7_SIGNER_INFO_num(si_sk); i++) { si=sk_PKCS7_SIGNER_INFO_value(si_sk,i); if (si->pkey == NULL) continue; j=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == j) break; else btmp=BIO_next(btmp); } /* We now have the EVP_MD_CTX, lets do the * signing. */ EVP_MD_CTX_copy_ex(&ctx_tmp,mdc); if (!BUF_MEM_grow_clean(buf,EVP_PKEY_size(si->pkey))) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_BIO_LIB); goto err; } sk=si->auth_attr; /* If there are attributes, we add the digest * attribute and only sign the attributes */ if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_data[EVP_MAX_MD_SIZE], *abuf=NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *digest; ASN1_UTCTIME *sign_time; const EVP_MD *md_tmp; /* Add signing time if not already present */ if (!PKCS7_get_signed_attribute(si, NID_pkcs9_signingTime)) { sign_time=X509_gmtime_adj(NULL,0); PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME,sign_time); } /* Add digest */ md_tmp=EVP_MD_CTX_md(&ctx_tmp); EVP_DigestFinal_ex(&ctx_tmp,md_data,&md_len); digest=M_ASN1_OCTET_STRING_new(); M_ASN1_OCTET_STRING_set(digest,md_data,md_len); PKCS7_add_signed_attribute(si, NID_pkcs9_messageDigest, V_ASN1_OCTET_STRING,digest); /* Now sign the attributes */ EVP_SignInit_ex(&ctx_tmp,md_tmp,NULL); alen = ASN1_item_i2d((ASN1_VALUE *)sk,&abuf, ASN1_ITEM_rptr(PKCS7_ATTR_SIGN)); if(!abuf) goto err; EVP_SignUpdate(&ctx_tmp,abuf,alen); OPENSSL_free(abuf); } #ifndef OPENSSL_NO_DSA if (si->pkey->type == EVP_PKEY_DSA) ctx_tmp.digest=EVP_dss1(); #endif if (!EVP_SignFinal(&ctx_tmp,(unsigned char *)buf->data, (unsigned int *)&buf->length,si->pkey)) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_EVP_LIB); goto err; } if (!ASN1_STRING_set(si->enc_digest, (unsigned char *)buf->data,buf->length)) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,ERR_R_ASN1_LIB); goto err; } } } if (!PKCS7_is_detached(p7)) { btmp=BIO_find_type(bio,BIO_TYPE_MEM); if (btmp == NULL) { PKCS7err(PKCS7_F_PKCS7_DATASIGN,PKCS7_R_UNABLE_TO_FIND_MEM_BIO); goto err; } BIO_get_mem_ptr(btmp,&buf_mem); /* Mark the BIO read only then we can use its copy of the data * instead of making an extra copy. */ BIO_set_flags(btmp, BIO_FLAGS_MEM_RDONLY); BIO_set_mem_eof_return(btmp, 0); os->data = (unsigned char *)buf_mem->data; os->length = buf_mem->length; #if 0 M_ASN1_OCTET_STRING_set(os, (unsigned char *)buf_mem->data,buf_mem->length); #endif } ret=1; err: EVP_MD_CTX_cleanup(&ctx_tmp); if (buf != NULL) BUF_MEM_free(buf); return(ret); }
static int rsa_cms_decrypt(CMS_RecipientInfo *ri) { EVP_PKEY_CTX *pkctx; X509_ALGOR *cmsalg; int nid; int rv = -1; unsigned char *label = NULL; int labellen = 0; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_OAEP_PARAMS *oaep; X509_ALGOR *maskHash; pkctx = CMS_RecipientInfo_get0_pkey_ctx(ri); if (!pkctx) return 0; if (!CMS_RecipientInfo_ktri_get0_algs(ri, NULL, NULL, &cmsalg)) return -1; nid = OBJ_obj2nid(cmsalg->algorithm); if (nid == NID_rsaEncryption) return 1; if (nid != NID_rsaesOaep) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_ENCRYPTION_TYPE); return -1; } /* Decode OAEP parameters */ oaep = rsa_oaep_decode(cmsalg, &maskHash); if (oaep == NULL) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_OAEP_PARAMETERS); goto err; } mgf1md = rsa_mgf1_to_md(oaep->maskGenFunc, maskHash); if (!mgf1md) goto err; md = rsa_algor_to_md(oaep->hashFunc); if (!md) goto err; if (oaep->pSourceFunc) { X509_ALGOR *plab = oaep->pSourceFunc; if (OBJ_obj2nid(plab->algorithm) != NID_pSpecified) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_UNSUPPORTED_LABEL_SOURCE); goto err; } if (plab->parameter->type != V_ASN1_OCTET_STRING) { RSAerr(RSA_F_RSA_CMS_DECRYPT, RSA_R_INVALID_LABEL); goto err; } label = plab->parameter->value.octet_string->data; /* Stop label being freed when OAEP parameters are freed */ plab->parameter->value.octet_string->data = NULL; labellen = plab->parameter->value.octet_string->length; } if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_OAEP_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_oaep_md(pkctx, md) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; if (EVP_PKEY_CTX_set0_rsa_oaep_label(pkctx, label, labellen) <= 0) goto err; /* Carry on */ rv = 1; err: RSA_OAEP_PARAMS_free(oaep); X509_ALGOR_free(maskHash); return rv; }
int PKCS7_signatureVerify(BIO *bio, PKCS7 *p7, PKCS7_SIGNER_INFO *si, X509 *x509) { ASN1_OCTET_STRING *os; EVP_MD_CTX mdc_tmp,*mdc; int ret=0,i; int md_type; STACK_OF(X509_ATTRIBUTE) *sk; BIO *btmp; EVP_PKEY *pkey; EVP_MD_CTX_init(&mdc_tmp); if (!PKCS7_type_is_signed(p7) && !PKCS7_type_is_signedAndEnveloped(p7)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_WRONG_PKCS7_TYPE); goto err; } md_type=OBJ_obj2nid(si->digest_alg->algorithm); btmp=bio; for (;;) { if ((btmp == NULL) || ((btmp=BIO_find_type(btmp,BIO_TYPE_MD)) == NULL)) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } BIO_get_md_ctx(btmp,&mdc); if (mdc == NULL) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, ERR_R_INTERNAL_ERROR); goto err; } if (EVP_MD_CTX_type(mdc) == md_type) break; /* Workaround for some broken clients that put the signature * OID instead of the digest OID in digest_alg->algorithm */ if (EVP_MD_pkey_type(EVP_MD_CTX_md(mdc)) == md_type) break; btmp=BIO_next(btmp); } /* mdc is the digest ctx that we want, unless there are attributes, * in which case the digest is the signed attributes */ EVP_MD_CTX_copy_ex(&mdc_tmp,mdc); sk=si->auth_attr; if ((sk != NULL) && (sk_X509_ATTRIBUTE_num(sk) != 0)) { unsigned char md_dat[EVP_MAX_MD_SIZE], *abuf = NULL; unsigned int md_len, alen; ASN1_OCTET_STRING *message_digest; EVP_DigestFinal_ex(&mdc_tmp,md_dat,&md_len); message_digest=PKCS7_digest_from_attributes(sk); if (!message_digest) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_UNABLE_TO_FIND_MESSAGE_DIGEST); goto err; } if ((message_digest->length != (int)md_len) || (memcmp(message_digest->data,md_dat,md_len))) { #if 0 { int ii; for (ii=0; ii<message_digest->length; ii++) printf("%02X",message_digest->data[ii]); printf(" sent\n"); for (ii=0; ii<md_len; ii++) printf("%02X",md_dat[ii]); printf(" calc\n"); } #endif PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_DIGEST_FAILURE); ret= -1; goto err; } EVP_VerifyInit_ex(&mdc_tmp,EVP_get_digestbynid(md_type), NULL); alen = ASN1_item_i2d((ASN1_VALUE *)sk, &abuf, ASN1_ITEM_rptr(PKCS7_ATTR_VERIFY)); EVP_VerifyUpdate(&mdc_tmp, abuf, alen); OPENSSL_free(abuf); } os=si->enc_digest; pkey = X509_get_pubkey(x509); if (!pkey) { ret = -1; goto err; } #ifndef OPENSSL_NO_DSA if(pkey->type == EVP_PKEY_DSA) mdc_tmp.digest=EVP_dss1(); #endif i=EVP_VerifyFinal(&mdc_tmp,os->data,os->length, pkey); EVP_PKEY_free(pkey); if (i <= 0) { PKCS7err(PKCS7_F_PKCS7_SIGNATUREVERIFY, PKCS7_R_SIGNATURE_FAILURE); ret= -1; goto err; } else ret=1; err: EVP_MD_CTX_cleanup(&mdc_tmp); return(ret); }
CMS_SignerInfo *CMS_add1_signer(CMS_ContentInfo *cms, X509 *signer, EVP_PKEY *pk, const EVP_MD *md, unsigned int flags) { CMS_SignedData *sd; CMS_SignerInfo *si = NULL; X509_ALGOR *alg; int i, type; if (!X509_check_private_key(signer, pk)) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE); return NULL; } sd = cms_signed_data_init(cms); if (!sd) goto err; si = M_ASN1_new_of(CMS_SignerInfo); if (!si) goto merr; X509_check_purpose(signer, -1, -1); CRYPTO_add(&pk->references, 1, CRYPTO_LOCK_EVP_PKEY); CRYPTO_add(&signer->references, 1, CRYPTO_LOCK_X509); si->pkey = pk; si->signer = signer; EVP_MD_CTX_init(&si->mctx); si->pctx = NULL; if (flags & CMS_USE_KEYID) { si->version = 3; if (sd->version < 3) sd->version = 3; type = CMS_SIGNERINFO_KEYIDENTIFIER; } else { type = CMS_SIGNERINFO_ISSUER_SERIAL; si->version = 1; } if (!cms_set1_SignerIdentifier(si->sid, signer, type)) goto err; if (md == NULL) { int def_nid; if (EVP_PKEY_get_default_digest_nid(pk, &def_nid) <= 0) goto err; md = EVP_get_digestbynid(def_nid); if (md == NULL) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DEFAULT_DIGEST); goto err; } } if (!md) { CMSerr(CMS_F_CMS_ADD1_SIGNER, CMS_R_NO_DIGEST_SET); goto err; } X509_ALGOR_set_md(si->digestAlgorithm, md); /* See if digest is present in digestAlgorithms */ for (i = 0; i < sk_X509_ALGOR_num(sd->digestAlgorithms); i++) { ASN1_OBJECT *aoid; alg = sk_X509_ALGOR_value(sd->digestAlgorithms, i); X509_ALGOR_get0(&aoid, NULL, NULL, alg); if (OBJ_obj2nid(aoid) == EVP_MD_type(md)) break; } if (i == sk_X509_ALGOR_num(sd->digestAlgorithms)) { alg = X509_ALGOR_new(); if (!alg) goto merr; X509_ALGOR_set_md(alg, md); if (!sk_X509_ALGOR_push(sd->digestAlgorithms, alg)) { X509_ALGOR_free(alg); goto merr; } } if (!(flags & CMS_KEY_PARAM) && !cms_sd_asn1_ctrl(si, 0)) goto err; if (!(flags & CMS_NOATTR)) { /* * Initialialize signed attributes strutucture so other attributes * such as signing time etc are added later even if we add none here. */ if (!si->signedAttrs) { si->signedAttrs = sk_X509_ATTRIBUTE_new_null(); if (!si->signedAttrs) goto merr; } if (!(flags & CMS_NOSMIMECAP)) { STACK_OF(X509_ALGOR) *smcap = NULL; i = CMS_add_standard_smimecap(&smcap); if (i) i = CMS_add_smimecap(si, smcap); sk_X509_ALGOR_pop_free(smcap, X509_ALGOR_free); if (!i) goto merr; } if (flags & CMS_REUSE_DIGEST) { if (!cms_copy_messageDigest(cms, si)) goto err; if (!(flags & (CMS_PARTIAL | CMS_KEY_PARAM)) && !CMS_SignerInfo_sign(si)) goto err; } } if (!(flags & CMS_NOCERTS)) { /* NB ignore -1 return for duplicate cert */ if (!CMS_add1_cert(cms, signer)) goto merr; } if (flags & CMS_KEY_PARAM) { if (flags & CMS_NOATTR) { si->pctx = EVP_PKEY_CTX_new(si->pkey, NULL); if (!si->pctx) goto err; if (EVP_PKEY_sign_init(si->pctx) <= 0) goto err; if (EVP_PKEY_CTX_set_signature_md(si->pctx, md) <= 0) goto err; } else if (EVP_DigestSignInit(&si->mctx, &si->pctx, md, NULL, pk) <= 0) goto err; } if (!sd->signerInfos) sd->signerInfos = sk_CMS_SignerInfo_new_null(); if (!sd->signerInfos || !sk_CMS_SignerInfo_push(sd->signerInfos, si)) goto merr; return si; merr: CMSerr(CMS_F_CMS_ADD1_SIGNER, ERR_R_MALLOC_FAILURE); err: if (si) M_ASN1_free_of(si, CMS_SignerInfo); return NULL; }
static void x509v3_cache_extensions(X509 *x) { BASIC_CONSTRAINTS *bs; PROXY_CERT_INFO_EXTENSION *pci; ASN1_BIT_STRING *usage; ASN1_BIT_STRING *ns; EXTENDED_KEY_USAGE *extusage; X509_EXTENSION *ex; size_t i; int j; CRYPTO_STATIC_MUTEX_lock_write(&g_x509_cache_extensions_lock); if(x->ex_flags & EXFLAG_SET) { CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock); return; } X509_digest(x, EVP_sha1(), x->sha1_hash, NULL); /* V1 should mean no extensions ... */ if(!X509_get_version(x)) x->ex_flags |= EXFLAG_V1; /* Handle basic constraints */ if((bs=X509_get_ext_d2i(x, NID_basic_constraints, NULL, NULL))) { if(bs->ca) x->ex_flags |= EXFLAG_CA; if(bs->pathlen) { if((bs->pathlen->type == V_ASN1_NEG_INTEGER) || !bs->ca) { x->ex_flags |= EXFLAG_INVALID; x->ex_pathlen = 0; } else x->ex_pathlen = ASN1_INTEGER_get(bs->pathlen); } else x->ex_pathlen = -1; BASIC_CONSTRAINTS_free(bs); x->ex_flags |= EXFLAG_BCONS; } /* Handle proxy certificates */ if((pci=X509_get_ext_d2i(x, NID_proxyCertInfo, NULL, NULL))) { if (x->ex_flags & EXFLAG_CA || X509_get_ext_by_NID(x, NID_subject_alt_name, -1) >= 0 || X509_get_ext_by_NID(x, NID_issuer_alt_name, -1) >= 0) { x->ex_flags |= EXFLAG_INVALID; } if (pci->pcPathLengthConstraint) { x->ex_pcpathlen = ASN1_INTEGER_get(pci->pcPathLengthConstraint); } else x->ex_pcpathlen = -1; PROXY_CERT_INFO_EXTENSION_free(pci); x->ex_flags |= EXFLAG_PROXY; } /* Handle key usage */ if((usage=X509_get_ext_d2i(x, NID_key_usage, NULL, NULL))) { if(usage->length > 0) { x->ex_kusage = usage->data[0]; if(usage->length > 1) x->ex_kusage |= usage->data[1] << 8; } else x->ex_kusage = 0; x->ex_flags |= EXFLAG_KUSAGE; ASN1_BIT_STRING_free(usage); } x->ex_xkusage = 0; if((extusage=X509_get_ext_d2i(x, NID_ext_key_usage, NULL, NULL))) { x->ex_flags |= EXFLAG_XKUSAGE; for(i = 0; i < sk_ASN1_OBJECT_num(extusage); i++) { switch(OBJ_obj2nid(sk_ASN1_OBJECT_value(extusage,i))) { case NID_server_auth: x->ex_xkusage |= XKU_SSL_SERVER; break; case NID_client_auth: x->ex_xkusage |= XKU_SSL_CLIENT; break; case NID_email_protect: x->ex_xkusage |= XKU_SMIME; break; case NID_code_sign: x->ex_xkusage |= XKU_CODE_SIGN; break; case NID_ms_sgc: case NID_ns_sgc: x->ex_xkusage |= XKU_SGC; break; case NID_OCSP_sign: x->ex_xkusage |= XKU_OCSP_SIGN; break; case NID_time_stamp: x->ex_xkusage |= XKU_TIMESTAMP; break; case NID_dvcs: x->ex_xkusage |= XKU_DVCS; break; case NID_anyExtendedKeyUsage: x->ex_xkusage |= XKU_ANYEKU; break; } } sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); } if((ns=X509_get_ext_d2i(x, NID_netscape_cert_type, NULL, NULL))) { if(ns->length > 0) x->ex_nscert = ns->data[0]; else x->ex_nscert = 0; x->ex_flags |= EXFLAG_NSCERT; ASN1_BIT_STRING_free(ns); } x->skid =X509_get_ext_d2i(x, NID_subject_key_identifier, NULL, NULL); x->akid =X509_get_ext_d2i(x, NID_authority_key_identifier, NULL, NULL); /* Does subject name match issuer ? */ if(!X509_NAME_cmp(X509_get_subject_name(x), X509_get_issuer_name(x))) { x->ex_flags |= EXFLAG_SI; /* If SKID matches AKID also indicate self signed */ if (X509_check_akid(x, x->akid) == X509_V_OK) x->ex_flags |= EXFLAG_SS; } x->altname = X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL); x->nc = X509_get_ext_d2i(x, NID_name_constraints, &j, NULL); if (!x->nc && (j != -1)) x->ex_flags |= EXFLAG_INVALID; setup_crldp(x); for (j = 0; j < X509_get_ext_count(x); j++) { ex = X509_get_ext(x, j); if (OBJ_obj2nid(X509_EXTENSION_get_object(ex)) == NID_freshest_crl) x->ex_flags |= EXFLAG_FRESHEST; if (!X509_EXTENSION_get_critical(ex)) continue; if (!X509_supported_extension(ex)) { x->ex_flags |= EXFLAG_CRITICAL; break; } } x->ex_flags |= EXFLAG_SET; CRYPTO_STATIC_MUTEX_unlock(&g_x509_cache_extensions_lock); }
int X509_REQ_print_ex(BIO *bio, X509_REQ *x, unsigned long nmflags, unsigned long cflag) { long l; EVP_PKEY *pkey; STACK_OF(X509_ATTRIBUTE) * sk; char mlch = ' '; int nmindent = 0; if ((nmflags & XN_FLAG_SEP_MASK) == XN_FLAG_SEP_MULTILINE) { mlch = '\n'; nmindent = 12; } if (nmflags == X509_FLAG_COMPAT) { nmindent = 16; } X509_REQ_INFO *ri = x->req_info; if (!(cflag & X509_FLAG_NO_HEADER)) { if (BIO_write(bio, "Certificate Request:\n", 21) <= 0 || BIO_write(bio, " Data:\n", 10) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_VERSION)) { l = X509_REQ_get_version(x); if (BIO_printf(bio, "%8sVersion: %ld (0x%lx)\n", "", l + 1, l) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_SUBJECT)) { if (BIO_printf(bio, " Subject:%c", mlch) <= 0 || X509_NAME_print_ex(bio, ri->subject, nmindent, nmflags) < 0 || BIO_write(bio, "\n", 1) <= 0) { goto err; } } if (!(cflag & X509_FLAG_NO_PUBKEY)) { if (BIO_write(bio, " Subject Public Key Info:\n", 33) <= 0 || BIO_printf(bio, "%12sPublic Key Algorithm: ", "") <= 0 || i2a_ASN1_OBJECT(bio, ri->pubkey->algor->algorithm) <= 0 || BIO_puts(bio, "\n") <= 0) { goto err; } pkey = X509_REQ_get_pubkey(x); if (pkey == NULL) { BIO_printf(bio, "%12sUnable to load Public Key\n", ""); ERR_print_errors(bio); } else { EVP_PKEY_print_public(bio, pkey, 16, NULL); EVP_PKEY_free(pkey); } } if (!(cflag & X509_FLAG_NO_ATTRIBUTES)) { if (BIO_printf(bio, "%8sAttributes:\n", "") <= 0) { goto err; } sk = x->req_info->attributes; if (sk_X509_ATTRIBUTE_num(sk) == 0) { if (BIO_printf(bio, "%12sa0:00\n", "") <= 0) { goto err; } } else { size_t i; for (i = 0; i < sk_X509_ATTRIBUTE_num(sk); i++) { X509_ATTRIBUTE *a = sk_X509_ATTRIBUTE_value(sk, i); ASN1_OBJECT *aobj = X509_ATTRIBUTE_get0_object(a); if (X509_REQ_extension_nid(OBJ_obj2nid(aobj))) { continue; } if (BIO_printf(bio, "%12s", "") <= 0) { goto err; } const int num_attrs = X509_ATTRIBUTE_count(a); const int obj_str_len = i2a_ASN1_OBJECT(bio, aobj); if (obj_str_len <= 0) { if (BIO_puts(bio, "(Unable to print attribute ID.)\n") < 0) { goto err; } else { continue; } } int j; for (j = 0; j < num_attrs; j++) { const ASN1_TYPE *at = X509_ATTRIBUTE_get0_type(a, j); const int type = at->type; ASN1_BIT_STRING *bs = at->value.asn1_string; int k; for (k = 25 - obj_str_len; k > 0; k--) { if (BIO_write(bio, " ", 1) != 1) { goto err; } } if (BIO_puts(bio, ":") <= 0) { goto err; } if (type == V_ASN1_PRINTABLESTRING || type == V_ASN1_UTF8STRING || type == V_ASN1_IA5STRING || type == V_ASN1_T61STRING) { if (BIO_write(bio, (char *)bs->data, bs->length) != bs->length) { goto err; } BIO_puts(bio, "\n"); } else { BIO_puts(bio, "unable to print attribute\n"); } } } } } if (!(cflag & X509_FLAG_NO_EXTENSIONS)) { STACK_OF(X509_EXTENSION) *exts = X509_REQ_get_extensions(x); if (exts) { BIO_printf(bio, "%8sRequested Extensions:\n", ""); size_t i; for (i = 0; i < sk_X509_EXTENSION_num(exts); i++) { X509_EXTENSION *ex = sk_X509_EXTENSION_value(exts, i); if (BIO_printf(bio, "%12s", "") <= 0) { goto err; } ASN1_OBJECT *obj = X509_EXTENSION_get_object(ex); i2a_ASN1_OBJECT(bio, obj); const int is_critical = X509_EXTENSION_get_critical(ex); if (BIO_printf(bio, ": %s\n", is_critical ? "critical" : "") <= 0) { goto err; } if (!X509V3_EXT_print(bio, ex, cflag, 16)) { BIO_printf(bio, "%16s", ""); ASN1_STRING_print(bio, X509_EXTENSION_get_data(ex)); } if (BIO_write(bio, "\n", 1) <= 0) { goto err; } } sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free); } } if (!(cflag & X509_FLAG_NO_SIGDUMP) && !X509_signature_print(bio, x->sig_alg, x->signature)) { goto err; } return 1; err: OPENSSL_PUT_ERROR(X509, X509_REQ_print_ex, ERR_R_BUF_LIB); return 0; }
int int_rsa_verify(int dtype, const unsigned char *m, unsigned int m_len, unsigned char *rm, size_t *prm_len, const unsigned char *sigbuf, size_t siglen, RSA *rsa) { int i, ret = 0, sigtype; unsigned char *s; X509_SIG *sig = NULL; if (siglen != (unsigned int)RSA_size(rsa)) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_WRONG_SIGNATURE_LENGTH); return 0; } if ((dtype == NID_md5_sha1) && rm) { i = RSA_public_decrypt((int)siglen, sigbuf, rm, rsa, RSA_PKCS1_PADDING); if (i <= 0) return 0; *prm_len = i; return 1; } s = malloc((unsigned int)siglen); if (s == NULL) { RSAerr(RSA_F_INT_RSA_VERIFY, ERR_R_MALLOC_FAILURE); goto err; } if (dtype == NID_md5_sha1 && m_len != SSL_SIG_LENGTH) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_MESSAGE_LENGTH); goto err; } i = RSA_public_decrypt((int)siglen, sigbuf, s, rsa, RSA_PKCS1_PADDING); if (i <= 0) goto err; /* * Oddball MDC2 case: signature can be OCTET STRING. * check for correct tag and length octets. */ if (dtype == NID_mdc2 && i == 18 && s[0] == 0x04 && s[1] == 0x10) { if (rm) { memcpy(rm, s + 2, 16); *prm_len = 16; ret = 1; } else if (memcmp(m, s + 2, 16)) RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); else ret = 1; } /* Special case: SSL signature */ if (dtype == NID_md5_sha1) { if (i != SSL_SIG_LENGTH || memcmp(s, m, SSL_SIG_LENGTH)) RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); else ret = 1; } else { const unsigned char *p = s; sig = d2i_X509_SIG(NULL, &p, (long)i); if (sig == NULL) goto err; /* Excess data can be used to create forgeries */ if (p != s + i) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } /* Parameters to the signature algorithm can also be used to create forgeries */ if (sig->algor->parameter && ASN1_TYPE_get(sig->algor->parameter) != V_ASN1_NULL) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); goto err; } sigtype = OBJ_obj2nid(sig->algor->algorithm); if (sigtype != dtype) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_ALGORITHM_MISMATCH); goto err; } if (rm) { const EVP_MD *md; md = EVP_get_digestbynid(dtype); if (md && (EVP_MD_size(md) != sig->digest->length)) RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_INVALID_DIGEST_LENGTH); else { memcpy(rm, sig->digest->data, sig->digest->length); *prm_len = sig->digest->length; ret = 1; } } else if ((unsigned int)sig->digest->length != m_len || memcmp(m, sig->digest->data, m_len) != 0) { RSAerr(RSA_F_INT_RSA_VERIFY, RSA_R_BAD_SIGNATURE); } else ret = 1; } err: if (sig != NULL) X509_SIG_free(sig); if (s != NULL) { OPENSSL_cleanse(s, (unsigned int)siglen); free(s); } return ret; }
int X509_get_signature_nid(const X509 *x) { return OBJ_obj2nid(x->sig_alg.algorithm); }
/* Customised RSA item verification routine. This is called * when a signature is encountered requiring special handling. We * currently only handle PSS. */ static int rsa_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it, void *asn, X509_ALGOR *sigalg, ASN1_BIT_STRING *sig, EVP_PKEY *pkey) { int rv = -1; int saltlen; const EVP_MD *mgf1md = NULL, *md = NULL; RSA_PSS_PARAMS *pss; X509_ALGOR *maskHash; EVP_PKEY_CTX *pkctx; /* Sanity check: make sure it is PSS */ if (OBJ_obj2nid(sigalg->algorithm) != NID_rsassaPss) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_SIGNATURE_TYPE); return -1; } /* Decode PSS parameters */ pss = rsa_pss_decode(sigalg, &maskHash); if (pss == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_PSS_PARAMETERS); goto err; } /* Check mask and lookup mask hash algorithm */ if (pss->maskGenAlgorithm) { if (OBJ_obj2nid(pss->maskGenAlgorithm->algorithm) != NID_mgf1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_ALGORITHM); goto err; } if (!maskHash) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNSUPPORTED_MASK_PARAMETER); goto err; } mgf1md = EVP_get_digestbyobj(maskHash->algorithm); if (mgf1md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_MASK_DIGEST); goto err; } } else mgf1md = EVP_sha1(); if (pss->hashAlgorithm) { md = EVP_get_digestbyobj(pss->hashAlgorithm->algorithm); if (md == NULL) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_UNKNOWN_PSS_DIGEST); goto err; } } else md = EVP_sha1(); if (pss->saltLength) { saltlen = ASN1_INTEGER_get(pss->saltLength); /* Could perform more salt length sanity checks but the main * RSA routines will trap other invalid values anyway. */ if (saltlen < 0) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_SALT_LENGTH); goto err; } } else saltlen = 20; /* low-level routines support only trailer field 0xbc (value 1) * and PKCS#1 says we should reject any other value anyway. */ if (pss->trailerField && ASN1_INTEGER_get(pss->trailerField) != 1) { RSAerr(RSA_F_RSA_ITEM_VERIFY, RSA_R_INVALID_TRAILER); goto err; } /* We have all parameters now set up context */ if (!EVP_DigestVerifyInit(ctx, &pkctx, md, NULL, pkey)) goto err; if (EVP_PKEY_CTX_set_rsa_padding(pkctx, RSA_PKCS1_PSS_PADDING) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_pss_saltlen(pkctx, saltlen) <= 0) goto err; if (EVP_PKEY_CTX_set_rsa_mgf1_md(pkctx, mgf1md) <= 0) goto err; /* Carry on */ rv = 2; err: RSA_PSS_PARAMS_free(pss); if (maskHash) X509_ALGOR_free(maskHash); return rv; }