static int check_bl3x_key_cert(const unsigned char *buf, size_t len, const unsigned char *i_key, size_t i_key_len, unsigned char *s_key, size_t *s_key_len, const char *key_oid) { const unsigned char *p; size_t sz; int err, flags; x509_crt_init(&cert); /* Parse key certificate */ err = x509_crt_parse(&cert, buf, len); if (err) { ERROR("Key certificate parse error %d.\n", err); goto error; } /* Verify certificate */ err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); if (err) { ERROR("Key certificate verification error %d. Flags: " "0x%x.\n", err, flags); goto error; } /* Check that the certificate has been signed by the issuer */ err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); if (err < 0) { ERROR("Error loading key in DER format %d.\n", err); goto error; } sz = (size_t)err; p = pk_buf + sizeof(pk_buf) - sz; if ((sz != i_key_len) || memcmp(p, i_key, sz)) { ERROR("Key certificate not signed with issuer key\n"); err = 1; goto error; } /* Get the content certificate key */ err = x509_get_crt_ext_data(&p, &sz, &cert, key_oid); if (err) { ERROR("Extension %s not found in Key certificate\n", key_oid); goto error; } assert(sz <= RSA_PUB_DER_MAX_BYTES); memcpy(s_key, p, sz); *s_key_len = sz; error: x509_crt_free(&cert); return err; }
/* * Parse and verify the BL2 certificate * * This function verifies the integrity of the BL2 certificate, checks that it * has been signed with the ROT key and extracts the BL2 hash stored in the * certificate so it can be matched later against the calculated hash. * * Return: 0 = success, Otherwise = error */ static int check_bl2_cert(unsigned char *buf, size_t len) { const unsigned char *p; size_t sz; int err, flags; x509_crt_init(&cert); /* Parse the BL2 certificate */ err = x509_crt_parse(&cert, buf, len); if (err) { ERROR("BL2 certificate parse error %d.\n", err); goto error; } /* Check that it has been signed with the ROT key */ err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); if (err < 0) { ERROR("Error loading ROT key in DER format %d.\n", err); goto error; } sz = (size_t)err; p = pk_buf + sizeof(pk_buf) - sz; err = plat_match_rotpk(p, sz); if (err) { ERROR("ROT and BL2 certificate key mismatch\n"); goto error; } /* Verify certificate */ err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); if (err) { ERROR("BL2 certificate verification error %d. Flags: 0x%x.\n", err, flags); goto error; } /* Extract BL2 image hash from certificate */ err = x509_get_crt_ext_data(&p, &sz, &cert, BL2_HASH_OID); if (err) { ERROR("Cannot read BL2 hash from certificate\n"); goto error; } assert(sz == SHA_BYTES + 2); /* Skip the tag and length bytes and copy the hash */ p += 2; memcpy(sha_bl2, p, SHA_BYTES); error: x509_crt_free(&cert); return err; }
static int check_bl3x_cert(unsigned char *buf, size_t len, const unsigned char *i_key, size_t i_key_len, const char *hash_oid, unsigned char *sha) { const unsigned char *p; size_t sz; int err, flags; x509_crt_init(&cert); /* Parse BL31 content certificate */ err = x509_crt_parse(&cert, buf, len); if (err) { ERROR("Content certificate parse error %d.\n", err); goto error; } /* Verify certificate */ err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); if (err) { ERROR("Content certificate verification error %d. Flags: " "0x%x.\n", err, flags); goto error; } /* Check that content certificate has been signed with the content * certificate key corresponding to this image */ sz = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); p = pk_buf + sizeof(pk_buf) - sz; if ((sz != i_key_len) || memcmp(p, i_key, sz)) { ERROR("Content certificate not signed with content " "certificate key\n"); err = 1; goto error; } /* Extract image hash from certificate */ err = x509_get_crt_ext_data(&p, &sz, &cert, hash_oid); if (err) { ERROR("Cannot read hash from certificate\n"); goto error; } assert(sz == SHA_BYTES + 2); /* Skip the tag and length bytes and copy the hash */ p += 2; memcpy(sha, p, SHA_BYTES); error: x509_crt_free(&cert); return err; }
AString cRSAPrivateKey::GetPubKeyDER(void) { class cPubKey { public: cPubKey(rsa_context * a_Rsa) : m_IsValid(false) { pk_init(&m_Key); if (pk_init_ctx(&m_Key, pk_info_from_type(POLARSSL_PK_RSA)) != 0) { ASSERT(!"Cannot init PrivKey context"); return; } if (rsa_copy(pk_rsa(m_Key), a_Rsa) != 0) { ASSERT(!"Cannot copy PrivKey to PK context"); return; } m_IsValid = true; } ~cPubKey() { if (m_IsValid) { pk_free(&m_Key); } } operator pk_context * (void) { return &m_Key; } protected: bool m_IsValid; pk_context m_Key; } PkCtx(&m_Rsa); unsigned char buf[3000]; int res = pk_write_pubkey_der(PkCtx, buf, sizeof(buf)); if (res < 0) { return AString(); } return AString((const char *)(buf + sizeof(buf) - res), (size_t)res); }
static int write_public_key( pk_context *key, const char *output_file ) { int ret; FILE *f; unsigned char output_buf[16000]; unsigned char *c = output_buf; size_t len = 0; memset(output_buf, 0, 16000); #if defined(POLARSSL_PEM_WRITE_C) if( opt.output_format == OUTPUT_FORMAT_PEM ) { if( ( ret = pk_write_pubkey_pem( key, output_buf, 16000 ) ) != 0 ) return( ret ); len = strlen( (char *) output_buf ); } else #endif { if( ( ret = pk_write_pubkey_der( key, output_buf, 16000 ) ) < 0 ) return( ret ); len = ret; c = output_buf + sizeof(output_buf) - len - 1; } if( ( f = fopen( output_file, "w" ) ) == NULL ) return( -1 ); if( fwrite( c, 1, len, f ) != len ) { fclose( f ); return( -1 ); } fclose( f ); return( 0 ); }
int pk_write_pubkey_pem( pk_context *key, unsigned char *buf, size_t size ) { int ret; unsigned char output_buf[1280000]; size_t olen = 0; if( ( ret = pk_write_pubkey_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) { return( ret ); } if( ( ret = pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, output_buf + sizeof(output_buf) - ret, ret, buf, size, &olen ) ) != 0 ) { return( ret ); } return( 0 ); }
result_t PKey::exportDer(obj_ptr<Buffer_base> &retVal) { result_t hr; bool priv; hr = isPrivate(priv); if (hr < 0) return hr; int ret; std::string buf; buf.resize(8192); if (priv) ret = pk_write_key_der(&m_key, (unsigned char *)&buf[0], buf.length()); else ret = pk_write_pubkey_der(&m_key, (unsigned char *)&buf[0], buf.length()); if (ret < 0) return CHECK_ERROR(_ssl::setError(ret)); retVal = new Buffer(buf.substr(buf.length() - ret)); return 0; }
static CURLcode polarssl_connect_step2(struct connectdata *conn, int sockindex) { int ret; struct Curl_easy *data = conn->data; struct ssl_connect_data* connssl = &conn->ssl[sockindex]; char buffer[1024]; const char * const pinnedpubkey = SSL_IS_PROXY() ? data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY] : data->set.str[STRING_SSL_PINNEDPUBLICKEY_ORIG]; char errorbuf[128]; errorbuf[0] = 0; conn->recv[sockindex] = polarssl_recv; conn->send[sockindex] = polarssl_send; ret = ssl_handshake(&BACKEND->ssl); switch(ret) { case 0: break; case POLARSSL_ERR_NET_WANT_READ: connssl->connecting_state = ssl_connect_2_reading; return CURLE_OK; case POLARSSL_ERR_NET_WANT_WRITE: connssl->connecting_state = ssl_connect_2_writing; return CURLE_OK; default: error_strerror(ret, errorbuf, sizeof(errorbuf)); failf(data, "ssl_handshake returned - PolarSSL: (-0x%04X) %s", -ret, errorbuf); return CURLE_SSL_CONNECT_ERROR; } infof(data, "PolarSSL: Handshake complete, cipher is %s\n", ssl_get_ciphersuite(&BACKEND->ssl) ); ret = ssl_get_verify_result(&BACKEND->ssl); if(ret && SSL_CONN_CONFIG(verifypeer)) { if(ret & BADCERT_EXPIRED) failf(data, "Cert verify failed: BADCERT_EXPIRED"); if(ret & BADCERT_REVOKED) { failf(data, "Cert verify failed: BADCERT_REVOKED"); return CURLE_SSL_CACERT; } if(ret & BADCERT_CN_MISMATCH) failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); if(ret & BADCERT_NOT_TRUSTED) failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); return CURLE_PEER_FAILED_VERIFICATION; } if(ssl_get_peer_cert(&(BACKEND->ssl))) { /* If the session was resumed, there will be no peer certs */ memset(buffer, 0, sizeof(buffer)); if(x509_crt_info(buffer, sizeof(buffer), (char *)"* ", ssl_get_peer_cert(&(BACKEND->ssl))) != -1) infof(data, "Dumping cert info:\n%s\n", buffer); } /* adapted from mbedtls.c */ if(pinnedpubkey) { int size; CURLcode result; x509_crt *p; unsigned char pubkey[PUB_DER_MAX_BYTES]; const x509_crt *peercert; peercert = ssl_get_peer_cert(&BACKEND->ssl); if(!peercert || !peercert->raw.p || !peercert->raw.len) { failf(data, "Failed due to missing peer certificate"); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } p = calloc(1, sizeof(*p)); if(!p) return CURLE_OUT_OF_MEMORY; x509_crt_init(p); /* Make a copy of our const peercert because pk_write_pubkey_der needs a non-const key, for now. https://github.com/ARMmbed/mbedtls/issues/396 */ if(x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { failf(data, "Failed copying peer certificate"); x509_crt_free(p); free(p); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } size = pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); if(size <= 0) { failf(data, "Failed copying public key from peer certificate"); x509_crt_free(p); free(p); return CURLE_SSL_PINNEDPUBKEYNOTMATCH; } /* pk_write_pubkey_der writes data at the end of the buffer. */ result = Curl_pin_peer_pubkey(data, pinnedpubkey, &pubkey[PUB_DER_MAX_BYTES - size], size); if(result) { x509_crt_free(p); free(p); return result; } x509_crt_free(p); free(p); } #ifdef HAS_ALPN if(conn->bits.tls_enable_alpn) { const char *next_protocol = ssl_get_alpn_protocol(&BACKEND->ssl); if(next_protocol != NULL) { infof(data, "ALPN, server accepted to use %s\n", next_protocol); #ifdef USE_NGHTTP2 if(!strncmp(next_protocol, NGHTTP2_PROTO_VERSION_ID, NGHTTP2_PROTO_VERSION_ID_LEN)) { conn->negnpn = CURL_HTTP_VERSION_2; } else #endif if(!strncmp(next_protocol, ALPN_HTTP_1_1, ALPN_HTTP_1_1_LENGTH)) { conn->negnpn = CURL_HTTP_VERSION_1_1; } } else infof(data, "ALPN, server did not agree to a protocol\n"); } #endif connssl->connecting_state = ssl_connect_3; infof(data, "SSL connected\n"); return CURLE_OK; }
int x509write_csr_der( x509write_csr *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); if( len ) { ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SET ) ); ASN1_CHK_ADD( len, asn1_write_oid( &c, tmp_buf, OID_PKCS9_CSR_EXT_REQ, OID_SIZE( OID_PKCS9_CSR_EXT_REQ ) ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); } ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_CONTEXT_SPECIFIC ) ); ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ ASN1_CHK_ADD( len, asn1_write_int( &c, tmp_buf, 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Prepare signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } if( pk_can_do( ctx->key, POLARSSL_PK_RSA ) ) pk_alg = POLARSSL_PK_RSA; else if( pk_can_do( ctx->key, POLARSSL_PK_ECDSA ) ) pk_alg = POLARSSL_PK_ECDSA; else return( POLARSSL_ERR_X509_INVALID_ALG ); if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); if( len > (size_t)( c2 - buf ) ) return( POLARSSL_ERR_ASN1_BUF_TOO_SMALL ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }
static int check_trusted_key_cert(unsigned char *buf, size_t len) { const unsigned char *p; size_t sz; int err, flags; x509_crt_init(&cert); /* Parse the Trusted Key certificate */ err = x509_crt_parse(&cert, buf, len); if (err) { ERROR("Trusted Key certificate parse error %d.\n", err); goto error; } /* Verify Trusted Key certificate */ err = x509_crt_verify(&cert, &cert, NULL, NULL, &flags, NULL, NULL); if (err) { ERROR("Trusted Key certificate verification error %d. Flags: " "0x%x.\n", err, flags); goto error; } /* Check that it has been signed with the ROT key */ err = pk_write_pubkey_der(&cert.pk, pk_buf, sizeof(pk_buf)); if (err < 0) { ERROR("Error loading ROT key in DER format %d.\n", err); goto error; } sz = (size_t)err; p = pk_buf + sizeof(pk_buf) - sz; if (plat_match_rotpk(p, sz)) { ERROR("ROT and Trusted Key certificate key mismatch\n"); goto error; } /* Extract Trusted World key from extensions */ err = x509_get_crt_ext_data(&p, &tz_world_pk_len, &cert, TZ_WORLD_PK_OID); if (err) { ERROR("Cannot read Trusted World key\n"); goto error; } assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES); memcpy(tz_world_pk, p, tz_world_pk_len); /* Extract Non-Trusted World key from extensions */ err = x509_get_crt_ext_data(&p, &ntz_world_pk_len, &cert, NTZ_WORLD_PK_OID); if (err) { ERROR("Cannot read Non-Trusted World key\n"); goto error; } assert(tz_world_pk_len <= RSA_PUB_DER_MAX_BYTES); memcpy(ntz_world_pk, p, ntz_world_pk_len); error: x509_crt_free(&cert); return err; }
int x509write_crt_der( x509write_cert *ctx, unsigned char *buf, size_t size, int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) { int ret; const char *sig_oid; size_t sig_oid_len = 0; unsigned char *c, *c2; unsigned char hash[64]; unsigned char sig[POLARSSL_MPI_MAX_SIZE]; unsigned char tmp_buf[2048]; size_t sub_len = 0, pub_len = 0, sig_and_oid_len = 0, sig_len; size_t len = 0; pk_type_t pk_alg; /* * Prepare data to be signed in tmp_buf */ c = tmp_buf + sizeof( tmp_buf ); /* Signature algorithm needed in TBS, and later for actual signature */ pk_alg = pk_get_type( ctx->issuer_key ); if( pk_alg == POLARSSL_PK_ECKEY ) pk_alg = POLARSSL_PK_ECDSA; if( ( ret = oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg, &sig_oid, &sig_oid_len ) ) != 0 ) { return( ret ); } /* * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension */ ASN1_CHK_ADD( len, x509_write_extensions( &c, tmp_buf, ctx->extensions ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 3 ) ); /* * SubjectPublicKeyInfo */ ASN1_CHK_ADD( pub_len, pk_write_pubkey_der( ctx->subject_key, tmp_buf, c - tmp_buf ) ); c -= pub_len; len += pub_len; /* * Subject ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->subject ) ); /* * Validity ::= SEQUENCE { * notBefore Time, * notAfter Time } */ sub_len = 0; ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_after, X509_RFC5280_UTC_TIME_LEN ) ); ASN1_CHK_ADD( sub_len, x509_write_time( &c, tmp_buf, ctx->not_before, X509_RFC5280_UTC_TIME_LEN ) ); len += sub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Issuer ::= Name */ ASN1_CHK_ADD( len, x509_write_names( &c, tmp_buf, ctx->issuer ) ); /* * Signature ::= AlgorithmIdentifier */ ASN1_CHK_ADD( len, asn1_write_algorithm_identifier( &c, tmp_buf, sig_oid, strlen( sig_oid ), 0 ) ); /* * Serial ::= INTEGER */ ASN1_CHK_ADD( len, asn1_write_mpi( &c, tmp_buf, &ctx->serial ) ); /* * Version ::= INTEGER { v1(0), v2(1), v3(2) } */ sub_len = 0; ASN1_CHK_ADD( sub_len, asn1_write_int( &c, tmp_buf, ctx->version ) ); len += sub_len; ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, sub_len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONTEXT_SPECIFIC | ASN1_CONSTRUCTED | 0 ) ); ASN1_CHK_ADD( len, asn1_write_len( &c, tmp_buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c, tmp_buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); /* * Make signature */ md( md_info_from_type( ctx->md_alg ), c, len, hash ); if( ( ret = pk_sign( ctx->issuer_key, ctx->md_alg, hash, 0, sig, &sig_len, f_rng, p_rng ) ) != 0 ) { return( ret ); } /* * Write data to output buffer */ c2 = buf + size; ASN1_CHK_ADD( sig_and_oid_len, x509_write_sig( &c2, buf, sig_oid, sig_oid_len, sig, sig_len ) ); c2 -= len; memcpy( c2, c, len ); len += sig_and_oid_len; ASN1_CHK_ADD( len, asn1_write_len( &c2, buf, len ) ); ASN1_CHK_ADD( len, asn1_write_tag( &c2, buf, ASN1_CONSTRUCTED | ASN1_SEQUENCE ) ); return( (int) len ); }