Skip to content

Commit 993a29f

Browse files
silbeigrr
authored andcommitted
Add support for verifying SHA-256 hash of Subject Public Key Info (esp8266#31)
For HTTP public key pinning (RFC7469), the SHA-256 hash of the Subject Public Key Info (which usually only changes when the public key changes) is used rather than the SHA-1 hash of the entire certificate (which will change on each certificate renewal).
1 parent d768568 commit 993a29f

File tree

4 files changed

+46
-3
lines changed

4 files changed

+46
-3
lines changed

ssl/crypto_misc.h

+1
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ struct _x509_ctx
7878
RSA_CTX *rsa_ctx;
7979
bigint *digest;
8080
uint8_t *fingerprint;
81+
uint8_t *spki_sha256;
8182
struct _x509_ctx *next;
8283
};
8384

ssl/ssl.h

+9
Original file line numberDiff line numberDiff line change
@@ -416,6 +416,15 @@ EXP_FUNC int STDCALL ssl_verify_cert(const SSL *ssl);
416416
*/
417417
EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp);
418418

419+
/**
420+
* @brief Check if SHA256 hash of Subject Public Key Info matches the one given.
421+
*
422+
* @param ssl [in] An SSL object reference.
423+
* @param fp [in] SHA256 hash to match against
424+
* @return SSL_OK if the certificate is verified.
425+
*/
426+
EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash);
427+
419428
/**
420429
* @brief Retrieve an X.509 distinguished name component.
421430
*

ssl/tls1.c

+19
Original file line numberDiff line numberDiff line change
@@ -2210,6 +2210,25 @@ EXP_FUNC int STDCALL ssl_match_fingerprint(const SSL *ssl, const uint8_t* fp)
22102210
return res;
22112211
}
22122212

2213+
EXP_FUNC int STDCALL ssl_match_spki_sha256(const SSL *ssl, const uint8_t* hash)
2214+
{
2215+
if (ssl->x509_ctx == NULL || ssl->x509_ctx->spki_sha256 == NULL)
2216+
return 1;
2217+
int res = memcmp(ssl->x509_ctx->spki_sha256, hash, SHA256_SIZE);
2218+
if (res != 0) {
2219+
printf("cert SPKI SHA-256 hash: ");
2220+
for (int i = 0; i < SHA256_SIZE; ++i) {
2221+
printf("%02X ", ssl->x509_ctx->spki_sha256[i]);
2222+
}
2223+
printf("\r\ntest hash: ");
2224+
for (int i = 0; i < SHA256_SIZE; ++i) {
2225+
printf("%02X ", hash[i]);
2226+
}
2227+
printf("\r\n");
2228+
}
2229+
return res;
2230+
}
2231+
22132232
#endif /* CONFIG_SSL_CERT_VERIFICATION */
22142233

22152234
/**

ssl/x509.c

+17-3
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ static const uint8_t *get_signature(const uint8_t *asn1_sig, int *len)
7171
*/
7272
int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
7373
{
74-
int begin_tbs, end_tbs;
74+
int begin_tbs, end_tbs, begin_spki, end_spki;
7575
int ret = X509_NOT_OK, offset = 0, cert_size = 0;
7676
X509_CTX *x509_ctx;
7777
#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)
113113

114114
if (asn1_name(cert, &offset, x509_ctx->ca_cert_dn) ||
115115
asn1_validity(cert, &offset, x509_ctx) ||
116-
asn1_name(cert, &offset, x509_ctx->cert_dn) ||
117-
asn1_public_key(cert, &offset, x509_ctx))
116+
asn1_name(cert, &offset, x509_ctx->cert_dn))
118117
{
119118
goto end_cert;
120119
}
120+
begin_spki = offset;
121+
if (asn1_public_key(cert, &offset, x509_ctx))
122+
goto end_cert;
123+
end_spki = offset;
121124

122125

123126
x509_ctx->fingerprint = malloc(SHA1_SIZE);
@@ -126,6 +129,12 @@ int x509_new(const uint8_t *cert, int *len, X509_CTX **ctx)
126129
SHA1_Update(&sha_fp_ctx, &cert[0], cert_size);
127130
SHA1_Final(x509_ctx->fingerprint, &sha_fp_ctx);
128131

132+
x509_ctx->spki_sha256 = malloc(SHA256_SIZE);
133+
SHA256_CTX spki_hash_ctx;
134+
SHA256_Init(&spki_hash_ctx);
135+
SHA256_Update(&spki_hash_ctx, &cert[begin_spki], end_spki-begin_spki);
136+
SHA256_Final(x509_ctx->spki_sha256, &spki_hash_ctx);
137+
129138
#ifdef CONFIG_SSL_CERT_VERIFICATION /* only care if doing verification */
130139
bi_ctx = x509_ctx->rsa_ctx->bi_ctx;
131140

@@ -289,6 +298,11 @@ void x509_free(X509_CTX *x509_ctx)
289298
free(x509_ctx->fingerprint);
290299
}
291300

301+
if (x509_ctx->spki_sha256)
302+
{
303+
free(x509_ctx->spki_sha256);
304+
}
305+
292306
if (x509_ctx->subject_alt_dnsnames)
293307
{
294308
for (i = 0; x509_ctx->subject_alt_dnsnames[i]; ++i)

0 commit comments

Comments
 (0)