/* * The native OpenSSL ECDSA key format contains both the private and public * components in one blob. This throws a bit of a monkey wrench into the API * here, as we only have one encoder - which requires a private key - and one * decoder, which can result in the decoding of either a public or a private * key. */ feeReturn feePubKeyCreateOpenSSLBlob( feePubKey pubKey, // private key unsigned char **keyBlob, // mallocd and RETURNED unsigned *keyBlobLen) // RETURNED { pubKeyInst *pkinst = (pubKeyInst *) pubKey; unsigned char *privStr = NULL; unsigned privStrLen = 0; feeReturn frtn = feeCreateECDSAPrivBlob(pubKey, &privStr, &privStrLen); if(frtn) { return frtn; } unsigned char *pubStr = NULL; unsigned pubStrLen = 0; frtn = feeCreateECDSAPubBlob(pubKey, &pubStr, &pubStrLen); if(frtn) { goto errOut; } frtn = feeDEREncodeOpenSSLPrivateKey(privStr, privStrLen, pubStr, pubStrLen, pkinst->cp, keyBlob, keyBlobLen); errOut: if(privStr) { ffree(privStr); } if(pubStr) { ffree(pubStr); } return frtn; }
void CryptKit::FEEBinaryKey::generateKeyBlob( Allocator &allocator, CssmData &blob, CSSM_KEYBLOB_FORMAT &format, AppleCSPSession &session, const CssmKey *paramKey, /* optional, unused here */ CSSM_KEYATTR_FLAGS &attrFlags) /* IN/OUT */ { unsigned char *keyBlob; unsigned len; feeReturn frtn = FR_Internal; bool freeTheKey = false; feePubKey keyToEncode = mFeeKey; assert(mFeeKey != NULL); if((format == CSSM_KEYBLOB_RAW_FORMAT_DIGEST) && (mKeyHeader.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY)) { /* key digest calculation; special case for private keys: cook * up the associated public key and encode that */ keyToEncode = feePubKeyAlloc(); if(keyToEncode == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } frtn = feePubKeyInitPubKeyFromPriv(mFeeKey, keyToEncode); if(frtn) { feePubKeyFree(keyToEncode); throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv"); } freeTheKey = true; } bool badFormat = false; int isPrivate = feePubKeyIsPrivate(keyToEncode); switch(mKeyHeader.AlgorithmId) { case CSSM_ALGID_FEE: if(isPrivate) { /* FEE private key */ switch(format) { case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: format = CSSM_KEYBLOB_RAW_FORMAT_NONE; /* and drop thru */ case CSSM_KEYBLOB_RAW_FORMAT_NONE: frtn = feePubKeyCreateDERPrivBlob(keyToEncode, &keyBlob, &len); break; case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: frtn = feePubKeyCreatePrivBlob(keyToEncode, &keyBlob, &len); break; default: badFormat = true; break; } } else { /* FEE Public key */ switch(format) { case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: format = CSSM_KEYBLOB_RAW_FORMAT_NONE; /* and drop thru */ case CSSM_KEYBLOB_RAW_FORMAT_NONE: frtn = feePubKeyCreateDERPubBlob(keyToEncode, &keyBlob, &len); break; case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: frtn = feePubKeyCreatePubBlob(keyToEncode, &keyBlob, &len); break; default: badFormat = true; break; } } /* end of base ALGID_FEE */ break; case CSSM_ALGID_ECDSA: if(isPrivate) { /* ECDSA/ECDH private key */ switch(format) { case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: /* ECDSA private key: PKCS8 */ frtn = feePubKeyCreatePKCS8Blob(keyToEncode, &keyBlob, &len); break; case CSSM_KEYBLOB_RAW_FORMAT_NONE: /* set to default format, drop thru */ format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL: /* ECDSA private key, SEC1/OpenSSL format */ frtn = feePubKeyCreateOpenSSLBlob(keyToEncode, &keyBlob, &len); break; case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; /* and drop thru */ case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: /* raw private key bytes */ frtn = feeCreateECDSAPrivBlob(keyToEncode, &keyBlob, &len); break; default: badFormat = true; break; } } else { /* * ECDSA public key. * Note there is no OpenSSL case here, that format is only generated for * private keys. */ switch(format) { case CSSM_KEYBLOB_RAW_FORMAT_NONE: /* set to default format, drop thru */ format = CSSM_KEYBLOB_RAW_FORMAT_X509; case CSSM_KEYBLOB_RAW_FORMAT_X509: /* ECDSA, public key, default: X509 */ frtn = feePubKeyCreateX509Blob(keyToEncode, &keyBlob, &len); break; case CSSM_KEYBLOB_RAW_FORMAT_DIGEST: format = CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING; /* and drop thru */ case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING: /* raw x|y string */ frtn = feeCreateECDSAPubBlob(keyToEncode, &keyBlob, &len); break; default: badFormat = true; break; } } /* end of case CSSM_ALGID_ECDSA */ break; default: /* not reached */ break; } if(badFormat) { CssmError::throwMe(isPrivate ? CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT : CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); } if(frtn) { throwCryptKit(frtn, "feePubKeyCreate*Blob"); } setUpCssmData(blob, len, allocator); memmove(blob.data(), keyBlob, len); blob.length(len); ffree(keyBlob); if(freeTheKey) { /* free the temp pub key we created here */ feePubKeyFree(keyToEncode); } }