void CryptKit::FEEECDSASigner::sign(
	const void	 	*data, 
	size_t 			dataLen,
	void			*sig,	
	size_t			*sigLen)	/* IN/OUT */
{
	unsigned char	*feeSig;
	unsigned		feeSigLen;
	feeReturn		frtn;
	
	if(mFeeKey == NULL) {
		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)");
	}
	frtn = feeECDSASign(mFeeKey,
		(unsigned char *)data,   // data to be signed
		(unsigned int)dataLen,				// in bytes
		mRandFcn, 
		mRandRef,
		&feeSig,
		&feeSigLen);			
	if(frtn) {
		throwCryptKit(frtn, "feeECDSASign");
	}
	/* copy out to caller and ffree */
	if(*sigLen < feeSigLen) {
		feeSigObjDebug("feeECDSASign overflow\n");
		ffree(feeSig);
		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
	}
	memmove(sig, feeSig, feeSigLen);
	*sigLen = feeSigLen;
	ffree(feeSig);

}
void CryptKit::FEERawSigner::verify(
	const void	 	*data, 
	size_t 			dataLen,
	const void		*sig,			
	size_t			sigLen)
{
	feeSig 		fsig;
	feeReturn	frtn;
	
	if(mFeeKey == NULL) {
		throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)");
	}
	frtn = feeSigParse((unsigned char *)sig, sigLen, &fsig);
	if(frtn) {
		throwCryptKit(frtn, "feeSigParse");
	}
	frtn = feeSigVerify(fsig,
		(unsigned char *)data,
		(unsigned int)dataLen,
		mFeeKey);
	feeSigFree(fsig);
	if(frtn) {
		throwCryptKit(frtn, NULL);
	}
}
size_t CryptKit::FEEECDSASigner::maxSigSize()
{
	unsigned 	rtn;
	feeReturn 	frtn;
	
	frtn = feeECDSASigSize(mFeeKey, &rtn);
	if(frtn) {
		throwCryptKit(frtn, "feeECDSASigSize");
	}
	return rtn;
}
void CryptKit::FEEECDSASigner::verify(
	const void	*data, 
	size_t 		dataLen,
	const void	*sig,			
	size_t		sigLen)
{
	feeReturn	frtn;

	if(mFeeKey == NULL) {
		throwCryptKit(FR_BadPubKey, "FEERawSigner::verify (no key)");
	}
	frtn = feeECDSAVerify((unsigned char *)sig,
		sigLen,
		(unsigned char *)data,
		(unsigned int)dataLen,
		mFeeKey);
	if(frtn) {
		throwCryptKit(frtn, NULL);
	}
}
/*
 * Note that, unlike the implementation in security_cryptkit/feePublicKey.c, we ignore
 * the Pm which used to be used as salt for the digest. That made staged verification
 * impossible and I do not believe it increased security. 
 */
void CryptKit::FEERawSigner::sign(
	const void	 	*data, 
	size_t 			dataLen,
	void			*sig,	
	size_t			*sigLen)	/* IN/OUT */
{
	feeSig 			fsig;
	feeReturn		frtn;
	unsigned char	*feeSig;
	unsigned		feeSigLen=0;
	
	if(mFeeKey == NULL) {
		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign (no key)");
	}
	fsig = feeSigNewWithKey(mFeeKey, mRandFcn, mRandRef);
	if(fsig == NULL) {
		throwCryptKit(FR_BadPubKey, "FEERawSigner::sign");
	}
	frtn = feeSigSign(fsig,
		(unsigned char *)data,
		(unsigned)dataLen,
		mFeeKey);
	if(frtn == FR_Success) {
		frtn = feeSigData(fsig, &feeSig, &feeSigLen);
	}
	feeSigFree(fsig);
	if(frtn) {
		throwCryptKit(frtn, "FEERawSigner::sign");
	}
	
	/* copy out to caller and ffree */
	if(*sigLen < feeSigLen) {
		feeSigObjDebug("FEERawSigner sign overflow\n");
		ffree(feeSig);
		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
	}
	memmove(sig, feeSig, feeSigLen);
	*sigLen = feeSigLen;
	ffree(feeSig);
}
Beispiel #6
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);
    }
}
Beispiel #7
0
// this one is specified in, and called from, AppleKeyPairGenContext
void CryptKit::FEEKeyPairGenContext::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.
     */
    FEEBinaryKey &fPubBinKey =
        dynamic_cast<FEEBinaryKey &>(pubBinKey);
    FEEBinaryKey &fPrivBinKey =
        dynamic_cast<FEEBinaryKey &>(privBinKey);

    /*
     * Two parameters from context. Key size in bits is required;
     * seed is optional. If not present, we cook up random private data.
     */
    keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH,
                             CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH);
    CssmCryptoData *cseed = context.get<CssmCryptoData>(CSSM_ATTRIBUTE_SEED);
    CssmData *seed;
    bool haveSeed;
    CssmAutoData aSeed(session());		// malloc on demand
    if(cseed) {
        /* caller specified seed */
        haveSeed = true;
        seed = &cseed->param();
    }
    else {
        /* generate random seed */
        haveSeed = false;
        unsigned keyBytes = ((keyBits + 7) / 8) + 1;
        aSeed.malloc(keyBytes);
        session().getRandomBytes(keyBytes, aSeed);
        seed = &aSeed.get();
    }

    CSSM_ALGORITHMS algId = context.algorithm();

    /* Curve and prime types - optional */
    feePrimeType primeType = FPT_Default;
    uint32 uPrimeType = context.getInt(CSSM_ATTRIBUTE_FEE_PRIME_TYPE);
    switch(uPrimeType) {
    case CSSM_FEE_PRIME_TYPE_DEFAULT:
        break;
    case CSSM_FEE_PRIME_TYPE_MERSENNE:
        primeType = FPT_Mersenne;
        break;
    case CSSM_FEE_PRIME_TYPE_FEE:
        primeType = FPT_FEE;
        break;
    case CSSM_FEE_PRIME_TYPE_GENERAL:
        primeType = FPT_General;
        break;
    default:
        /* FIXME - maybe we should be more specific */
        CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
    }
    feeCurveType curveType = FCT_Default;
    switch(algId) {
    case CSSM_ALGID_ECDSA:
        /* no options */
        curveType = FCT_ANSI;
        break;
    default:
    {
        uint32 uCurveType = context.getInt(CSSM_ATTRIBUTE_FEE_CURVE_TYPE);
        switch(uCurveType) {
        case CSSM_FEE_CURVE_TYPE_DEFAULT:
            break;
        case CSSM_FEE_CURVE_TYPE_MONTGOMERY:
            curveType = FCT_Montgomery;
            break;
        case CSSM_FEE_CURVE_TYPE_WEIERSTRASS:
            curveType = FCT_Weierstrass;
            break;
        case CSSM_FEE_CURVE_TYPE_ANSI_X9_62:
            curveType = FCT_ANSI;
            break;
        default:
            /* FIXME - maybe we should be more specific */
            CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_ALG_PARAMS);
        }
        break;
    }
    }
    feeReturn frtn = feePubKeyInitFromPrivDataKeyBits(
                         fPrivBinKey.feeKey(),
                         (unsigned char *)seed->data(),
                         (unsigned int)seed->length(),
                         keyBits,
                         primeType,
                         curveType,
                         /*
                          * our random seed: trust it
                          * caller's seed: hash it
                          */
                         haveSeed ? 1 : 0);
    if(frtn) {
        throwCryptKit(frtn, "feePubKeyInitFromPrivDataKeyBits");
    }
    frtn = feePubKeyInitPubKeyFromPriv(fPrivBinKey.feeKey(),
                                       fPubBinKey.feeKey());
    if(frtn) {
        throwCryptKit(frtn, "feePubKeyInitPubKeyFromPriv");
    }
}
/* 
 * Convert a raw CssmKey to a newly alloc'd feePubKey.
 */
feePubKey CryptKit::rawCssmKeyToFee(
	const CssmKey	&cssmKey)
{
	const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
	assert(hdr->BlobType == CSSM_KEYBLOB_RAW); 
	
	switch(hdr->AlgorithmId) {
		case CSSM_ALGID_FEE:
		case CSSM_ALGID_ECDSA:
			break;
		default:
			// someone else's key (should never happen)
			CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
	}
	
	switch(hdr->KeyClass) {
		case CSSM_KEYCLASS_PUBLIC_KEY:
		case CSSM_KEYCLASS_PRIVATE_KEY:
			break;
		default:
			// someone else's key
			CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
	}
	
	feePubKey feeKey = feePubKeyAlloc();
	if(feeKey == NULL) {
		CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
	}
	
	feeReturn frtn = FR_IllegalArg;
	bool badFormat = false;
				
	/*
	 * The actual key init depends on key type and incoming format
	 */
	switch(hdr->AlgorithmId) {
		case CSSM_ALGID_FEE:
			switch(hdr->KeyClass) {
				case CSSM_KEYCLASS_PUBLIC_KEY:
					switch(hdr->Format) {
						case FEE_KEYBLOB_DEFAULT_FORMAT:
							/* FEE, public key, default: custom DER */
							frtn = feePubKeyInitFromDERPubBlob(feeKey,
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
						case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
							/* FEE, public key, native byte stream */
							frtn = feePubKeyInitFromPubBlob(feeKey,
								cssmKey.KeyData.Data,
								(unsigned int)cssmKey.KeyData.Length);
							break;
						default:
							badFormat = true;
							break;
					}
					break;
				case CSSM_KEYCLASS_PRIVATE_KEY:
					switch(hdr->Format) {
						case FEE_KEYBLOB_DEFAULT_FORMAT:
							/* FEE, private key, default: custom DER */
							frtn = feePubKeyInitFromDERPrivBlob(feeKey,
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
						case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
							/* FEE, private key, native byte stream */
							frtn = feePubKeyInitFromPrivBlob(feeKey,
								cssmKey.KeyData.Data,
								(unsigned int)cssmKey.KeyData.Length);
							break;
						default:
							badFormat = true;
							break;
					}
					break;
				default:
					/* not reached, we already checked */
					break;
			}
			/* end of case ALGID_FEE */
			break;
			
		case CSSM_ALGID_ECDSA:
			switch(hdr->KeyClass) {
				case CSSM_KEYCLASS_PUBLIC_KEY:
					switch(hdr->Format) {
						case CSSM_KEYBLOB_RAW_FORMAT_NONE:
						case CSSM_KEYBLOB_RAW_FORMAT_X509:
							/* ECDSA, public key, default: X509 */
							frtn = feePubKeyInitFromX509Blob(feeKey,
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
							
						case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
							/*
							 * An oddity here: we can parse this incoming key, but 
							 * it contains both private and public parts. We throw
							 * out the private component here.
							 */
							frtn = feePubKeyInitFromOpenSSLBlob(feeKey, 
								1,		/* pubOnly */
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
						/* 
						 * NOTE: we cannot *import* a key in raw X9.62 format.
						 * We'd need to know the curve, i.e., the feeDepth.
						 * I suppose we could infer that from the blob length but
						 * a better way would be to have a new context attribute
						 * specifying which curve.
						 * For now, imported raw keys have to be in X509 format.
						 */
						case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
						default:
							badFormat = true;
							break;
					}
					break;
				case CSSM_KEYCLASS_PRIVATE_KEY:
					switch(hdr->Format) {
						case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:
							/* ECDSA, private key, PKCS8 */
							frtn = feePubKeyInitFromPKCS8Blob(feeKey,
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
							
						case CSSM_KEYBLOB_RAW_FORMAT_NONE:
						case CSSM_KEYBLOB_RAW_FORMAT_OPENSSL:
							/* ECDSA, private, default: OpenSSL */
							/* see comment above re: OpenSSL public/private keys */
							frtn = feePubKeyInitFromOpenSSLBlob(feeKey, 
								0,		/* pubOnly */
								cssmKey.KeyData.Data,
								cssmKey.KeyData.Length);
							break;
						/* see comment above about X9.62 format public key blobs */
						case CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING:
						default:
							badFormat = true;
							break;
					}
					break;
				default:
					/* not reached, we already checked */
					break;
			}
			/* end of case CSSM_ALGID_ECDSA */
			break;
	}
	if(badFormat) {
		CssmError::throwMe(hdr->KeyClass == CSSM_KEYCLASS_PRIVATE_KEY ?
			CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT :
			CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
	}
	if(frtn) {
		feePubKeyFree(feeKey);
		throwCryptKit(frtn, "feePubKeyInitFromKeyBlob");
	}
	return feeKey;
}