/* sign */ void DSASigner::sign( const void *data, size_t dataLen, void *sig, size_t *sigLen) /* IN/OUT */ { if(mDsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); } if(mDsaKey->priv_key == NULL) { CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS); } /* get signature in internal format */ DSA_SIG *dsaSig = DSA_do_sign((unsigned char *)data, dataLen, mDsaKey); if(dsaSig == NULL) { throwRsaDsa("DSA_do_sign"); } /* DER encode the signature */ CssmAutoData encodedSig(alloc()); int irtn = DSASigEncode(dsaSig, encodedSig); if(irtn) { throwRsaDsa("DSASigEncode"); } if(encodedSig.length() > *sigLen) { throwRsaDsa("DSA sign overflow"); } memmove(sig, encodedSig.data(), encodedSig.length()); *sigLen = encodedSig.length(); DSA_SIG_free(dsaSig); }
/* * Generate DSA algorithm parameters from optional seed input, returning result * into NSS_DSAAlgParamss.[pqg]. This is called from both GenerateParameters and from * KeyPairGenerate (if no GenerateParameters has yet been called). */ void DSAKeyPairGenContext::dsaGenParams( uint32 keySizeInBits, const void *inSeed, // optional unsigned inSeedLen, NSS_DSAAlgParams &algParams, SecNssCoder &coder) // contents of algParams mallocd from here { unsigned char seedBuf[SHA1_DIGEST_SIZE]; void *seedPtr; /* validate key size */ if((keySizeInBits < DSA_MIN_KEY_SIZE) || (keySizeInBits > DSA_MAX_KEY_SIZE) || (keySizeInBits & DSA_KEY_BITS_MASK)) { CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); } /* seed from one of three sources */ if(inSeed == NULL) { /* 20 random seed bytes */ session().getRandomBytes(SHA1_DIGEST_SIZE, seedBuf); seedPtr = seedBuf; } else if(inSeedLen == SHA1_DIGEST_SIZE) { /* perfect */ seedPtr = (void *)inSeed; } else { /* hash caller's seed */ cspGenSha1Hash(inSeed, inSeedLen, seedBuf); seedPtr = seedBuf; } DSA *dsaKey = DSA_generate_parameters(keySizeInBits, (unsigned char *)seedPtr, SHA1_DIGEST_SIZE, NULL, // counter_ret NULL, // h_ret NULL, NULL); if(dsaKey == NULL) { throwRsaDsa("DSA_generate_parameters"); } /* stuff dsaKey->[pqg] into a caller's NSS_DSAAlgParams */ bnToCssmData(dsaKey->p, algParams.p, coder); bnToCssmData(dsaKey->q, algParams.q, coder); bnToCssmData(dsaKey->g, algParams.g, coder); DSA_free(dsaKey); }
/* sign */ void RSASigner::sign( const void *data, size_t dataLen, void *sig, size_t *sigLen) /* IN/OUT */ { StLock<Mutex> _(gMutex()); if(mRsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_INTERNAL_ERROR); } /* get encoded digest info */ CssmAutoData encodedInfo(alloc()); int irtn = generateDigestInfo(data, dataLen, digestAlg(), encodedInfo, RSA_size(mRsaKey)); if(irtn) { rsaSigDebug("***digestInfo error\n"); throwOpensslErr(irtn); } /* signature := encrypted digest info */ irtn = RSA_private_encrypt(encodedInfo.length(), (unsigned char *)encodedInfo.data(), (unsigned char *)sig, mRsaKey, mPadding); if(irtn < 0) { throwRsaDsa("RSA_private_encrypt"); } if((unsigned)irtn > *sigLen) { rsaSigDebug("RSA_private_encrypt: sig overflow"); CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR); } *sigLen = (unsigned)irtn; }
void DeriveKey_DH ( const Context &context, const CssmData &Param, // other's public key. may be empty CSSM_DATA *keyData, // mallocd by caller // we fill in keyData->Length bytes AppleCSPSession &session) { bool mallocdPrivKey; size_t privSize; /* private DH key from context - required */ DH *privKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_KEY, CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey); if(privKey == NULL) { CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY); } cspDhDebug("DeriveKey_DH, privKey %p", privKey); privSize = DH_size(privKey); if(privSize < keyData->Length) { /* we've been asked for more bits than this key can generate */ CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE); } /* * Public key ("their" key) can come from two places: * -- in the context as a CSSM_ATTRIBUTE_PUBLIC_KEY. This is how * public keys in X509 format must be used in this function * -- in the incoming Param, the raw unformatted (PKCS3) form */ bool mallocdPubKey = false; BIGNUM *pubKeyBn = NULL; bool allocdPubKeyBn = false; DH *pubKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY, CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey); if(pubKey != NULL) { if(pubKey->pub_key == NULL) { errorLog0("DeriveKey_DH: public key in context with no pub_key\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } pubKeyBn = pubKey->pub_key; cspDhDebug("DeriveKey_DH, pubKey from context %p", pubKey); } else { if((Param.Data == NULL) || (Param.Length == 0)) { errorLog0("DeriveKey_DH: no pub_key, no Param\n"); CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); } pubKeyBn = BN_bin2bn(Param.Data, Param.Length, NULL); if(pubKeyBn == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } allocdPubKeyBn = true; cspDhDebug("DeriveKey_DH, no pubKey in context"); } unsigned char *buf = (unsigned char *)session.malloc(privSize); int rtn = DH_compute_key(buf, pubKeyBn, privKey); if(rtn > 0) { /* * FIXME : I have not found a specification describing *which* * bytes of the value we just computed we are supposed to * use as the actual key bytes. We use the M.S. bytes. * * Note that due to modulo arithmetic, we may have gotten fewer * bytes than we asked for. If so, the caller will have * to deal with that if they really need privSize bytes. */ assert((uint32)rtn <= privSize); uint32 toMove = keyData->Length; if((uint32)rtn < toMove) { toMove = (uint32)rtn; } memmove(keyData->Data, buf, toMove); keyData->Length = toMove; } if(mallocdPrivKey) { DH_free(privKey); } if(mallocdPubKey) { DH_free(pubKey); } if(allocdPubKeyBn) { BN_free(pubKeyBn); } session.free(buf); if(rtn <= 0) { throwRsaDsa("DH_compute_key"); } }
/* * This one is specified in, and called from, AppleKeyPairGenContext */ void DSAKeyPairGenContext::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. */ DSABinaryKey &rPubBinKey = dynamic_cast<DSABinaryKey &>(pubBinKey); DSABinaryKey &rPrivBinKey = dynamic_cast<DSABinaryKey &>(privBinKey); /* * Parameters from context: * Key size in bits, required; * {p,q,g} from generateParams, optional */ keyBits = context.getInt(CSSM_ATTRIBUTE_KEY_LENGTH, CSSMERR_CSP_MISSING_ATTR_KEY_LENGTH); if(keyBits > DSA_MAX_KEY_SIZE) { CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY_LENGTH); } CssmData *paramData = context.get<CssmData>(CSSM_ATTRIBUTE_ALG_PARAMS); NSS_DSAAlgParams algParams; SecNssCoder coder; // generated algParams mallocd from here if(paramData != NULL) { /* this contains the DER encoding of a NSS_DSAAlgParams */ CSSM_RETURN crtn = DSADecodeAlgParams(algParams, paramData->Data, (unsigned)paramData->Length, coder); if(crtn) { CssmError::throwMe(crtn); } } else { /* no alg params specified; generate them now using null (random) seed */ dsaGenParams(keyBits, NULL, 0, algParams, coder); } /* create key, stuff params into it */ rPrivBinKey.mDsaKey = DSA_new(); if(rPrivBinKey.mDsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } DSA *dsaKey = rPrivBinKey.mDsaKey; dsaKey->p = cssmDataToBn(algParams.p); dsaKey->q = cssmDataToBn(algParams.q); dsaKey->g = cssmDataToBn(algParams.g); /* generate the key (both public and private capabilities) */ int irtn = DSA_generate_key(dsaKey); if(!irtn) { throwRsaDsa("DSA_generate_key"); } /* public key is subset of private key */ rPubBinKey.mDsaKey = DSA_new(); if(rPrivBinKey.mDsaKey == NULL) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } DSA *pub = rPubBinKey.mDsaKey; DSA *priv = rPrivBinKey.mDsaKey; pub->p = BN_dup(priv->p); pub->q = BN_dup(priv->q); pub->g = BN_dup(priv->g); pub->pub_key = BN_dup(priv->pub_key); if((pub->p == NULL) || (pub->q == NULL) || (pub->g == NULL) || (pub->pub_key == NULL)) { CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR); } }