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