1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-08-12 20:49:16 +03:00

Add support for verifying SHA-256 hash of Subject Public Key Info (#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).
This commit is contained in:
silbe
2017-02-19 03:29:31 +01:00
committed by Ivan Grokhotkov
parent d768568ae7
commit 993a29f2b2
4 changed files with 46 additions and 3 deletions

View File

@@ -78,6 +78,7 @@ struct _x509_ctx
RSA_CTX *rsa_ctx;
bigint *digest;
uint8_t *fingerprint;
uint8_t *spki_sha256;
struct _x509_ctx *next;
};

View File

@@ -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.
*

View File

@@ -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 */
/**

View File

@@ -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)