diff --git a/certs/taoCert.txt b/certs/taoCert.txt index f0bb92101..15a12c059 100644 --- a/certs/taoCert.txt +++ b/certs/taoCert.txt @@ -30,6 +30,22 @@ same as self signed, use ca prefix instead of client 3) openssl x509 -req -in server-req.pem -days 1000 -md5 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem +***** Adding Subject Key ID and Authentication Key ID extensions to a cert ***** + +Create a config file for OpenSSL with the example contents: + + [skidakid] + subjectKeyIdentifier=hash + authorityKeyIdentifier=keyid + +Add to the openssl command for creating a cert signed by a CA step 3 the +following options: + + -extfile -extensions skidakid + +anywhere before the redirect. This will add the cert's public key hash as the +Subject Key Identifier, and the signer's SKID as the Authentication Key ID. + ***** To create a dsa cert ******************** diff --git a/ctaocrypt/src/asn.c b/ctaocrypt/src/asn.c index 9b33c282d..9b3329044 100644 --- a/ctaocrypt/src/asn.c +++ b/ctaocrypt/src/asn.c @@ -1218,7 +1218,7 @@ void InitDecodedCert(DecodedCert* cert, byte* source, word32 inSz, void* heap) cert->extAuthInfoSz = 0; cert->extCrlInfo = NULL; cert->extCrlInfoSz = 0; - cert->extSubjKeyId = NULL; + XMEMSET(cert->extSubjKeyId, 0, SHA_SIZE); cert->extSubjKeyIdSz = 0; cert->extAuthKeyId = NULL; cert->extAuthKeyIdSz = 0; @@ -2591,7 +2591,7 @@ static void DecodeSubjKeyId(byte* input, int sz, DecodedCert* cert) return; } - cert->extSubjKeyId = input + idx; + XMEMCPY(cert->extSubjKeyId, input + idx, length); cert->extSubjKeyIdSz = length; return; @@ -2723,6 +2723,9 @@ int ParseCert(DecodedCert* cert, int type, int verify, void* cm) extern "C" { #endif CYASSL_LOCAL Signer* GetCA(void* signers, byte* hash); + #ifndef NO_SKID + CYASSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); + #endif #ifdef __cplusplus } #endif @@ -2763,8 +2766,26 @@ int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) if (confirmOID != cert->signatureOID) return ASN_SIG_OID_E; + #ifndef NO_SKID + if (cert->extSubjKeyIdSz == 0) { + Sha sha; + InitSha(&sha); + ShaUpdate(&sha, cert->publicKey, cert->pubKeySize); + ShaFinal(&sha, cert->extSubjKeyId); + cert->extSubjKeyIdSz = SHA_SIZE; + } + #endif + if (verify && type != CA_TYPE) { - Signer* ca = GetCA(cm, cert->issuerHash); + Signer* ca; + #ifndef NO_SKID + if (cert->extAuthKeyId != NULL) + ca = GetCA(cm, cert->extAuthKeyId); + else + ca = GetCAByName(cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(cm, cert->issuerHash); + #endif /* NO SKID */ CYASSL_MSG("About to verify certificate signature"); if (ca) { @@ -5235,7 +5256,14 @@ int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0) return ASN_PARSE_E; - ca = GetCA(cm, dcrl->issuerHash); + #ifndef NO_SKID + if (dcrl->extAuthKeyId != NULL) + ca = GetCA(cm, dcrl->extAuthKeyId); + else + ca = GetCAByName(cm, dcrl->issuerHash); + #else /* NO_SKID */ + ca = GetCA(cm, dcrl->issuerHash); + #endif /* NO_SKID */ CYASSL_MSG("About to verify CRL signature"); if (ca) { diff --git a/cyassl/ctaocrypt/asn.h b/cyassl/ctaocrypt/asn.h index c5654276c..fcdc6c96a 100644 --- a/cyassl/ctaocrypt/asn.h +++ b/cyassl/ctaocrypt/asn.h @@ -251,7 +251,7 @@ struct DecodedCert { int extAuthInfoSz; /* length of the URI */ byte* extCrlInfo; /* CRL Distribution Points */ int extCrlInfoSz; /* length of the URI */ - byte* extSubjKeyId; /* Subject Key ID */ + byte extSubjKeyId[SHA_SIZE]; /* Subject Key ID */ int extSubjKeyIdSz; /* length of the ID */ byte* extAuthKeyId; /* Authority Key ID */ int extAuthKeyIdSz; /* length of the ID */ @@ -291,7 +291,12 @@ struct Signer { word32 pubKeySize; word32 keyOID; /* key type */ char* name; /* common name */ - byte hash[SIGNER_DIGEST_SIZE];/* sha hash of names in certificate */ + byte subjectNameHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #ifndef NO_SKID + byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #endif Signer* next; }; diff --git a/cyassl/internal.h b/cyassl/internal.h index 405758b4a..21c5c0557 100644 --- a/cyassl/internal.h +++ b/cyassl/internal.h @@ -1845,6 +1845,9 @@ CYASSL_LOCAL void ShrinkInputBuffer(CYASSL* ssl, int forcedFree); CYASSL_LOCAL void ShrinkOutputBuffer(CYASSL* ssl); #ifndef NO_CERTS CYASSL_LOCAL Signer* GetCA(void* cm, byte* hash); + #ifndef NO_SKID + CYASSL_LOCAL Signer* GetCAByName(void* cm, byte* hash); + #endif #endif CYASSL_LOCAL void BuildTlsFinished(CYASSL* ssl, Hashes* hashes, const byte* sender); diff --git a/src/internal.c b/src/internal.c index eb5eab23c..25aca4ea4 100644 --- a/src/internal.c +++ b/src/internal.c @@ -2931,17 +2931,24 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx) while (count > 1) { buffer myCert = certs[count - 1]; DecodedCert dCert; + byte* subjectHash; InitDecodedCert(&dCert, myCert.buffer, myCert.length, ssl->heap); ret = ParseCertRelative(&dCert, CERT_TYPE, !ssl->options.verifyNone, ssl->ctx->cm); + #ifndef NO_SKID + subjectHash = dCert.extSubjKeyId; + #else + subjectHash = dCert.subjectHash; + #endif + if (ret == 0 && dCert.isCA == 0) { CYASSL_MSG("Chain cert is not a CA, not adding as one"); } else if (ret == 0 && ssl->options.verifyNone) { CYASSL_MSG("Chain cert not verified by option, not adding as CA"); } - else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, dCert.subjectHash)) { + else if (ret == 0 && !AlreadySigner(ssl->ctx->cm, subjectHash)) { buffer add; add.length = myCert.length; add.buffer = (byte*)XMALLOC(myCert.length, ssl->heap, diff --git a/src/ssl.c b/src/ssl.c index 05cabd8fb..c69162d9f 100644 --- a/src/ssl.c +++ b/src/ssl.c @@ -880,7 +880,13 @@ int AlreadySigner(CYASSL_CERT_MANAGER* cm, byte* hash) return ret; signers = cm->caTable[row]; while (signers) { - if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SHA_DIGEST_SIZE) == 0) { ret = 1; break; } @@ -908,7 +914,13 @@ Signer* GetCA(void* vp, byte* hash) signers = cm->caTable[row]; while (signers) { - if (XMEMCMP(hash, signers->hash, SHA_DIGEST_SIZE) == 0) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SHA_DIGEST_SIZE) == 0) { ret = signers; break; } @@ -920,6 +932,37 @@ Signer* GetCA(void* vp, byte* hash) } +#ifndef NO_SKID +/* return CA if found, otherwise NULL. Walk through hash table. */ +Signer* GetCAByName(void* vp, byte* hash) +{ + CYASSL_CERT_MANAGER* cm = (CYASSL_CERT_MANAGER*)vp; + Signer* ret = NULL; + Signer* signers; + word32 row; + + if (cm == NULL) + return NULL; + + if (LockMutex(&cm->caLock) != 0) + return ret; + + for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) { + signers = cm->caTable[row]; + while (signers && ret == NULL) { + if (XMEMCMP(hash, signers->subjectNameHash, SHA_DIGEST_SIZE) == 0) { + ret = signers; + } + signers = signers->next; + } + } + UnLockMutex(&cm->caLock); + + return ret; +} +#endif + + /* owns der, internal now uses too */ /* type flag ids from user or from chain received during verify don't allow chain ones to be added w/o isCA extension */ @@ -929,17 +972,24 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) DecodedCert cert; Signer* signer = 0; word32 row; + byte* subjectHash; CYASSL_MSG("Adding a CA"); InitDecodedCert(&cert, der.buffer, der.length, cm->heap); ret = ParseCert(&cert, CA_TYPE, verify, cm); CYASSL_MSG(" Parsed new CA"); + #ifndef NO_SKID + subjectHash = cert.extSubjKeyId; + #else + subjectHash = cert.subjectHash; + #endif + if (ret == 0 && cert.isCA == 0 && type != CYASSL_USER_CA) { CYASSL_MSG(" Can't add as CA if not actually one"); ret = NOT_CA_ERROR; } - else if (ret == 0 && AlreadySigner(cm, cert.subjectHash)) { + else if (ret == 0 && AlreadySigner(cm, subjectHash)) { CYASSL_MSG(" Already have this CA, not adding again"); (void)ret; } @@ -953,13 +1003,21 @@ int AddCA(CYASSL_CERT_MANAGER* cm, buffer der, int type, int verify) signer->publicKey = cert.publicKey; signer->pubKeySize = cert.pubKeySize; signer->name = cert.subjectCN; - XMEMCPY(signer->hash, cert.subjectHash, SHA_DIGEST_SIZE); + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, + cert.extSubjKeyId, SHA_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert.subjectHash, SHA_DIGEST_SIZE); signer->next = NULL; /* in case lock fails */ cert.publicKey = 0; /* don't free here */ cert.subjectCN = 0; - row = HashSigner(signer->hash); + #ifndef NO_SKID + row = HashSigner(signer->subjectKeyIdHash); + #else + row = HashSigner(signer->subjectNameHash); + #endif if (LockMutex(&cm->caLock) == 0) { signer->next = cm->caTable[row];