// this one is specified in, and called from, AppleKeyPairGenContext void RSAKeyPairGenContext::generate( const Context &context, BinaryKey &pubBinKey, BinaryKey &privBinKey, uint32 &keyBits) { /* * These casts throw exceptions if the keys are of the * wrong classes, which would be a major bogon, since we created * the keys in the above generate() function. */ RSABinaryKey &rPubBinKey = dynamic_cast<RSABinaryKey &>(pubBinKey); RSABinaryKey &rPrivBinKey = dynamic_cast<RSABinaryKey &>(privBinKey); /* * One parameter from context: Key size in bits is required. * FIXME - get public exponent from context? */ keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); if(keyBits > rsaMaxKeySize()) { CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); } /* generate the private key */ rPrivBinKey.mRsaKey = RSA_generate_key(keyBits, RSA_PUB_EXPONENT, NULL, // no callback NULL); if(rPrivBinKey.mRsaKey == NULL) { rsaKeyDebug("RSA_generate_key returned NULL"); CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); // ??? } /* public key is subset of private key */ rPubBinKey.mRsaKey = RSA_new(); if(rPrivBinKey.mRsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } RSA *pub = rPubBinKey.mRsaKey; RSA *priv = rPrivBinKey.mRsaKey; pub->n = BN_dup(priv->n); pub->e = BN_dup(priv->e); if((pub->n == NULL) || (pub->e == NULL)) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } }
/* * Convert a raw CssmKey to a newly alloc'd RSA key. */ RSA *rawCssmKeyToRsa( const CssmKey &cssmKey, CSSM_DATA &label) // mallocd and RETURNED for OAEP keys { const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader; bool isPub; bool isOaep = false; assert(hdr->BlobType == CSSM_KEYBLOB_RAW); switch(hdr->AlgorithmId) { case CSSM_ALGID_RSA: break; case CSSM_ALGMODE_PKCS1_EME_OAEP: isOaep = true; break; default: // someone else's key (should never happen) CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); } /* validate and figure out what we're dealing with */ switch(hdr->KeyClass) { case CSSM_KEYCLASS_PUBLIC_KEY: switch(hdr->Format) { case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: case CSSM_KEYBLOB_RAW_FORMAT_X509: case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2: break; default: CssmError::throwMe( CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); } if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_X509)) { CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT); } isPub = true; break; case CSSM_KEYCLASS_PRIVATE_KEY: switch(hdr->Format) { case CSSM_KEYBLOB_RAW_FORMAT_PKCS8: // default case CSSM_KEYBLOB_RAW_FORMAT_PKCS1: // openssl style case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH: break; default: CssmError::throwMe( CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); } if(isOaep && (hdr->Format != CSSM_KEYBLOB_RAW_FORMAT_PKCS8)) { CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT); } isPub = false; break; default: CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } RSA *rsaKey = RSA_new(); if(rsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } CSSM_RETURN crtn; if(isOaep) { if(isPub) { crtn = RSAOAEPPublicKeyDecode(rsaKey, cssmKey.KeyData.Data, cssmKey.KeyData.Length, &label); } else { crtn = RSAOAEPPrivateKeyDecode(rsaKey, cssmKey.KeyData.Data, cssmKey.KeyData.Length, &label); } } else { if(isPub) { crtn = RSAPublicKeyDecode(rsaKey, hdr->Format, cssmKey.KeyData.Data, cssmKey.KeyData.Length); } else { crtn = RSAPrivateKeyDecode(rsaKey, hdr->Format, cssmKey.KeyData.Data, cssmKey.KeyData.Length); } } if(crtn) { RSA_free(rsaKey); CssmError::throwMe(crtn); } /* enforce max key size and max public exponent size */ bool badKey = false; uint32 keySize = RSA_size(rsaKey) * 8; if(keySize > rsaMaxKeySize()) { rsaMiscDebug("rawCssmKeyToRsa: key size exceeded"); badKey = true; } else { keySize = BN_num_bytes(rsaKey->e) * 8; if(keySize > rsaMaxPubExponentSize()) { badKey = true; rsaMiscDebug("rawCssmKeyToRsa: pub exponent size exceeded"); } } if(badKey) { RSA_free(rsaKey); CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); } return rsaKey; }