diff --git a/ssl/crypto_misc.h b/ssl/crypto_misc.h index 92494b605..d66839755 100644 --- a/ssl/crypto_misc.h +++ b/ssl/crypto_misc.h @@ -78,6 +78,7 @@ struct _x509_ctx RSA_CTX *rsa_ctx; bigint *digest; uint8_t *fingerprint; + uint8_t *spki_sha256; struct _x509_ctx *next; }; diff --git a/ssl/ssl.h b/ssl/ssl.h index 4869fa879..e2b220dd7 100644 --- a/ssl/ssl.h +++ b/ssl/ssl.h @@ -416,6 +416,15 @@ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl); */ EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp); +/** + * @brief Check if SHA256 hash of Subject Public Key Info matches the one given. + * + * @param ssl [in] An SSL object reference. + * @param fp [in] SHA256 hash to match against + * @return SSL_OK if the certificate is verified. + */ +EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash); + /** * @brief Retrieve an X.509 distinguished name component. * diff --git a/ssl/tls1.c b/ssl/tls1.c index 0cf2e4c2f..4066d4922 100644 --- a/ssl/tls1.c +++ b/ssl/tls1.c @@ -2210,6 +2210,25 @@ EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp) return res; } +EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash) +{ + if (ssl->x509_ctx == NULL || ssl->x509_ctx->spki_sha256 == NULL) + return 1; + int res = memcmp(ssl->x509_ctx->spki_sha256, hash, SHA256_SIZE); + if (res != 0) { + printf("cert SPKI SHA-256 hash: "); + for (int i = 0; i < SHA256_SIZE; ++i) { + printf("%02X ", ssl->x509_ctx->spki_sha256[i]); + } + printf("\r\ntest hash: "); + for (int i = 0; i < SHA256_SIZE; ++i) { + printf("%02X ", hash[i]); + } + printf("\r\n"); + } + return res; +} + #endif /* CONFIG_SSL_CERT_VERIFICATION */ /** diff --git a/ssl/x509.c b/ssl/x509.c index 862d897fb..35bd7281e 100644 --- a/ssl/x509.c +++ b/ssl/x509.c @@ -71,7 +71,7 @@ end_get_sig: */ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) { - int begin_tbs, end_tbs; + int begin_tbs, end_tbs, begin_spki, end_spki; int ret = X509_NOT_OK, offset = 0, cert_size = 0; X509_CTX *x509_ctx; #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ @@ -113,11 +113,14 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) || asn1_validity(cert, &offset, x509_ctx) || - asn1_name(cert, &offset, x509_ctx->cert_dn) || - asn1_public_key(cert, &offset, x509_ctx)) + asn1_name(cert, &offset, x509_ctx->cert_dn)) { goto end_cert; } + begin_spki = offset; + if (asn1_public_key(cert, &offset, x509_ctx)) + goto end_cert; + end_spki = offset; x509_ctx->fingerprint = malloc(SHA1_SIZE); @@ -126,6 +129,12 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx) SHA1_Update(&sha_fp_ctx, &cert[0], cert_size); SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx); + x509_ctx->spki_sha256 = malloc(SHA256_SIZE); + SHA256_CTX spki_hash_ctx; + SHA256_Init(&spki_hash_ctx); + SHA256_Update(&spki_hash_ctx, &cert[begin_spki], end_spki-begin_spki); + SHA256_Final(x509_ctx->spki_sha256, &spki_hash_ctx); + #ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */ bi_ctx = x509_ctx->rsa_ctx->bi_ctx; @@ -289,6 +298,11 @@ void x509_free(X509_CTX *x509_ctx) free(x509_ctx->fingerprint); } + if (x509_ctx->spki_sha256) + { + free(x509_ctx->spki_sha256); + } + if (x509_ctx->subject_alt_dnsnames) { for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)