// 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);		
	}
}
Exemple #2
0
/*
 * 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;
}