CCCryptorStatus CCRSAGetKeyComponents(CCRSACryptorRef rsaKey, uint8_t *modulus, size_t *modulusLength, uint8_t *exponent, size_t *exponentLength, uint8_t *p, size_t *pLength, uint8_t *q, size_t *qLength) { CCRSACryptor *rsa = rsaKey; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); switch(rsa->keyType) { case ccRSAKeyPublic: { if(ccrsa_get_pubkey_components(ccrsa_ctx_public(rsaKey->fk), modulus, modulusLength, exponent, exponentLength)) return kCCParamError; break; } case ccRSAKeyPrivate: { if(ccrsa_get_fullkey_components(rsaKey->fk, modulus, modulusLength, exponent, exponentLength, p, pLength, q, qLength)) return kCCParamError; break; } default: return kCCParamError; } return kCCSuccess; }
CCCryptorStatus CCRSACryptorVerify(CCRSACryptorRef publicKey, CCAsymmetricPadding padding, const void *hash, size_t hashLen, CCDigestAlgorithm digestType, size_t saltLen, const void *signedData, size_t signedDataLen) { bool valid; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!publicKey || !hash || !signedData) return kCCParamError; switch(padding) { case ccPKCS1Padding: if(ccrsa_verify_pkcs1v15(ccrsa_ctx_public(publicKey->fk), CCDigestGetDigestInfo(digestType)->oid, hashLen, hash, signedDataLen, signedData, &valid) != 0) return kCCDecodeError; if(!valid) return kCCDecodeError; break; case ccOAEPPadding: if(ccrsa_verify_oaep(ccrsa_ctx_public(publicKey->fk), CCDigestGetDigestInfo(digestType), hashLen, hash, signedDataLen, signedData, &valid) != 0) return kCCDecodeError; if(!valid) return kCCDecodeError; break; case ccX931Padding: case ccPKCS1PaddingRaw: case ccPaddingNone: default: return kCCParamError; break; } return kCCSuccess; }
CCCryptorStatus CCRSACryptorDecrypt(CCRSACryptorRef privateKey, CCAsymmetricPadding padding, const void *cipherText, size_t cipherTextLen, void *plainText, size_t *plainTextLen, const void *tagData, size_t tagDataLen, CCDigestAlgorithm digestType) { CCCryptorStatus retval = kCCSuccess; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!privateKey || !cipherText || !plainText || !plainTextLen) return kCCParamError; switch (padding) { case ccPKCS1Padding: if(ccrsa_decrypt_eme_pkcs1v15(privateKey->fk, plainTextLen, plainText, cipherTextLen, (uint8_t *) cipherText) != 0) retval = kCCDecodeError; break; case ccOAEPPadding: if(ccrsa_decrypt_oaep(privateKey->fk, CCDigestGetDigestInfo(digestType), plainTextLen, plainText, cipherTextLen, (uint8_t *) cipherText, tagDataLen, tagData) != 0) retval = kCCDecodeError; break; default: goto errOut; } errOut: return retval; }
CCCryptorStatus CCRSACryptorSign(CCRSACryptorRef privateKey, CCAsymmetricPadding padding, const void *hashToSign, size_t hashSignLen, CCDigestAlgorithm digestType, size_t saltLen, void *signedData, size_t *signedDataLen) { CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!privateKey || !hashToSign || !signedData) return kCCParamError; switch(padding) { case ccPKCS1Padding: if(ccrsa_sign_pkcs1v15(privateKey->fk, CCDigestGetDigestInfo(digestType)->oid, hashSignLen, hashToSign, signedDataLen, signedData) != 0) return kCCDecodeError; break; case ccOAEPPadding: if(ccrsa_sign_oaep(privateKey->fk, CCDigestGetDigestInfo(digestType), ccDRBGGetRngState(), hashSignLen, hashToSign, signedDataLen, signedData) != 0) return kCCDecodeError; break; case ccX931Padding: case ccPKCS1PaddingRaw: case ccPaddingNone: default: return kCCParamError; break; } return kCCSuccess; }
CCCryptorStatus CCRSACryptorExport(CCRSACryptorRef cryptor, void *out, size_t *outLen) { CCCryptorStatus retval = kCCSuccess; size_t bufsiz; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!cryptor || !out) return kCCParamError; switch(cryptor->keyType) { case ccRSAKeyPublic: bufsiz = ccrsa_export_pub_size(ccrsa_ctx_public(cryptor->fk)); if(*outLen <= bufsiz) { *outLen = bufsiz; return kCCBufferTooSmall; } *outLen = bufsiz; if(ccrsa_export_pub(ccrsa_ctx_public(cryptor->fk), bufsiz, out)) return kCCDecodeError; break; case ccRSAKeyPrivate: bufsiz = ccrsa_export_priv_size(cryptor->fk); if(*outLen < bufsiz) { *outLen = bufsiz; return kCCBufferTooSmall; } *outLen = bufsiz; if(ccrsa_export_priv(cryptor->fk, bufsiz, out)) return kCCDecodeError; break; default: retval = kCCParamError; } return retval; }
CCCryptorStatus CCRSACryptorCrypt(CCRSACryptorRef rsaKey, const void *in, size_t inLen, void *out, size_t *outLen) { CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!rsaKey || !in || !out || !outLen) return kCCParamError; size_t keysizeBytes = (rsaKey->keySize+7)/8; if(inLen != keysizeBytes || *outLen < keysizeBytes) return kCCMemoryFailure; cc_size n = ccrsa_ctx_n(rsaKey->fk); cc_unit buf[n]; ccn_read_uint(n, buf, inLen, in); switch(rsaKey->keyType) { case ccRSAKeyPublic: ccrsa_pub_crypt(ccrsa_ctx_public(rsaKey->fk), buf, buf); break; case ccRSAKeyPrivate: ccrsa_priv_crypt(ccrsa_ctx_private(rsaKey->fk), buf, buf); break; default: return kCCParamError; } *outLen = keysizeBytes; ccn_write_uint_padded(n, buf, *outLen, out); return kCCSuccess; }
CCCryptorStatus CCRSACryptorCreateFromData( CCRSAKeyType keyType, uint8_t *modulus, size_t modulusLength, uint8_t *exponent, size_t exponentLength, uint8_t *p, size_t pLength, uint8_t *q, size_t qLength, CCRSACryptorRef *ref) { CCCryptorStatus retval = kCCSuccess; CCRSACryptor *rsaKey = NULL; size_t n = ccn_nof_size(modulusLength); cc_unit m[n]; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); __Require_Action(ccn_read_uint(n, m, modulusLength, modulus) == 0, errOut, retval = kCCParamError); size_t nbits = ccn_bitlen(n, m); __Require_Action((rsaKey = ccMallocRSACryptor(nbits, keyType)) != NULL, errOut, retval = kCCMemoryFailure); __Require_Action(ccn_read_uint(n, ccrsa_ctx_m(rsaKey->fk), modulusLength, modulus) == 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(n, ccrsa_ctx_e(rsaKey->fk), exponentLength, exponent) == 0, errOut, retval = kCCParamError); cczp_init(ccrsa_ctx_zm(rsaKey->fk)); rsaKey->keySize = ccn_bitlen(n, ccrsa_ctx_m(rsaKey->fk)); switch(keyType) { case ccRSAKeyPublic: rsaKey->keyType = ccRSAKeyPublic; break; case ccRSAKeyPrivate: { ccrsa_priv_ctx_t privk = ccrsa_ctx_private(rsaKey->fk); size_t psize = ccn_nof_size(pLength); size_t qsize = ccn_nof_size(qLength); CCZP_N(ccrsa_ctx_private_zp(privk)) = psize; __Require_Action(ccn_read_uint(psize, CCZP_PRIME(ccrsa_ctx_private_zp(privk)), pLength, p) == 0, errOut, retval = kCCParamError); CCZP_N(ccrsa_ctx_private_zq(privk)) = qsize; __Require_Action(ccn_read_uint(qsize, CCZP_PRIME(ccrsa_ctx_private_zq(privk)), qLength, q) == 0, errOut, retval = kCCParamError); ccrsa_crt_makekey(ccrsa_ctx_zm(rsaKey->fk), ccrsa_ctx_e(rsaKey->fk), ccrsa_ctx_d(rsaKey->fk), ccrsa_ctx_private_zp(privk), ccrsa_ctx_private_dp(privk), ccrsa_ctx_private_qinv(privk), ccrsa_ctx_private_zq(privk), ccrsa_ctx_private_dq(privk)); rsaKey->keyType = ccRSAKeyPrivate; break; } default: retval = kCCParamError; goto errOut; } *ref = rsaKey; return kCCSuccess; errOut: if(rsaKey) ccRSACryptorClear(rsaKey); return retval; }
int CCRSAGetKeySize(CCRSACryptorRef key) { CCRSACryptor *cryptor = key; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(key == NULL) return kCCParamError; return (int) cryptor->keySize; }
CCRSACryptorRef CCRSACryptorGetPublicKeyFromPrivateKey(CCRSACryptorRef privateCryptorRef) { CCRSACryptor *publicCryptor = NULL, *privateCryptor = privateCryptorRef; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if((publicCryptor = ccMallocRSACryptor(privateCryptor->keySize, ccRSAKeyPublic)) == NULL) return NULL; ccrsa_init_pub(ccrsa_ctx_public(publicCryptor->fk), ccrsa_ctx_m(privateCryptor->fk), ccrsa_ctx_e(privateCryptor->fk)); publicCryptor->keyType = ccRSAKeyPublic; return publicCryptor; }
CCRSAKeyType CCRSAGetKeyType(CCRSACryptorRef key) { CCRSACryptor *cryptor = key; CCRSAKeyType retval; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(key == NULL) return ccRSABadKey; retval = cryptor->keyType; if(retval != ccRSAKeyPublic && retval != ccRSAKeyPrivate) return ccRSABadKey; return retval; }
void CCAESCmac(const void *key, const uint8_t *data, size_t dataLength, /* length of data in bytes */ void *macOut) /* MAC written here */ { uint8_t X[16],Y[16], M_last[16], padded[16]; uint8_t K1[16], K2[16]; int flag; size_t n; const struct ccmode_ecb *aesmode = getCipherMode(kCCAlgorithmAES128, kCCModeECB, kCCEncrypt).ecb; ccecb_ctx_decl(aesmode->size, ctx); CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); // CMacInit aesmode->init(aesmode, ctx, 16, key); aesmode->ecb(ctx, 1, Y, X); ccGenAESSubKey(aesmode, ctx, K1, K2); // CMacUpdates (all in this case) n = (dataLength+15) / 16; /* n is number of rounds */ if ( 0 == n ) { n = 1; flag = 0; } else { if ( (dataLength%16) == 0 ) flag = 1; else flag = 0; } if ( flag ) { /* last block is complete block */ xor_128(&data[16*(n-1)],K1,M_last); } else { ccAESCMacPadding(&data[16*(n-1)],padded,dataLength%16); xor_128(padded,K2,M_last); } memset(X, 0, 16); for (size_t i=0; i<n-1; i++ ) { xor_128(X,&data[16*i],Y); /* Y := Mi (+) X */ aesmode->ecb(ctx, 1, Y, X); } // CMacFinal xor_128(X,M_last,Y); aesmode->ecb(ctx, 1, Y, X); memcpy(macOut, X, 16); }
CCCryptorStatus CCRSACryptorImport(const void *keyPackage, size_t keyPackageLen, CCRSACryptorRef *key) { CCRSACryptor *cryptor = NULL; CCCryptorStatus retval; CCRSAKeyType keyToMake; cc_size keyN; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!keyPackage || !key) return kCCParamError; if((keyN = ccrsa_import_priv_n(keyPackageLen, keyPackage)) != 0) keyToMake = ccRSAKeyPrivate; else if((keyN = ccrsa_import_pub_n(keyPackageLen, keyPackage)) != 0) keyToMake = ccRSAKeyPublic; else return kCCDecodeError; __Require_Action((cryptor = ccMallocRSACryptor(kCCMaximumRSAKeyBits, keyToMake)) != NULL, errOut, retval = kCCMemoryFailure); switch(keyToMake) { case ccRSAKeyPublic: ccrsa_ctx_n(ccrsa_ctx_public(cryptor->fk)) = keyN; if(ccrsa_import_pub(ccrsa_ctx_public(cryptor->fk), keyPackageLen, keyPackage)) { ccRSACryptorClear(cryptor); return kCCDecodeError; } break; case ccRSAKeyPrivate: ccrsa_ctx_n(cryptor->fk) = keyN; if(ccrsa_import_priv(cryptor->fk, keyPackageLen, keyPackage)) { ccRSACryptorClear(cryptor); return kCCDecodeError; } break; } cryptor->keyType = keyToMake; *key = cryptor; cryptor->keySize = ccRSAkeysize(cryptor); return kCCSuccess; errOut: if(cryptor) ccRSACryptorClear(cryptor); *key = NULL; return retval; }
CCCryptorStatus CCRSACryptorGeneratePair(size_t keysize, uint32_t e, CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey) { CCCryptorStatus retval; CCRSACryptor *privateCryptor = NULL; CCRSACryptor *publicCryptor = NULL; struct ccrng_state *theRng1 = ccDRBGGetRngState(); struct ccrng_state *theRng2 = ccDevRandomGetRngState(); CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); // ccrsa_generate_key() requires the exponent as length / pointer to bytes cc_unit cc_unit_e = (cc_unit) e; size_t eSize = ccn_write_int_size(1, &cc_unit_e); uint8_t eBytes[eSize]; ccn_write_int(1, &cc_unit_e, eSize, eBytes); *publicKey = *privateKey = NULL; __Require_Action((privateCryptor = ccMallocRSACryptor(keysize, ccRSAKeyPrivate)) != NULL, errOut, retval = kCCMemoryFailure); // __Require_Action((ccrsa_generate_key(keysize, privateCryptor->rsaKey.full, sizeof(e), &e, theRng) == 0), errOut, retval = kCCDecodeError); __Require_Action((ccrsa_generate_931_key(keysize, privateCryptor->fk, eSize, eBytes, theRng1, theRng2) == 0), errOut, retval = kCCDecodeError); privateCryptor->keyType = ccRSAKeyPrivate; __Require_Action((publicCryptor = CCRSACryptorGetPublicKeyFromPrivateKey(privateCryptor)) != NULL, errOut, retval = kCCMemoryFailure); *publicKey = publicCryptor; *privateKey = privateCryptor; __Require_Action(ccRSApairwiseConsistencyCheck(*privateKey, *publicKey) == true, errOut, retval = kCCDecodeError); return kCCSuccess; errOut: if(privateCryptor) ccRSACryptorClear(privateCryptor); if(publicCryptor) ccRSACryptorClear(publicCryptor); *publicKey = *privateKey = NULL; return retval; }
uint CCCalibratePBKDF(CCPBKDFAlgorithm algorithm, size_t passwordLen, size_t saltLen, CCPseudoRandomAlgorithm prf, size_t derivedKeyLen, uint32_t msec) { char *password; uint8_t *salt; uint64_t startTime, endTime, elapsedTime; uint8_t *derivedKey; int i; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if (derivedKeyLen == 0) return -1; // bad parameters if (saltLen == 0 || saltLen > CC_MAX_PRF_WORKSPACE) return -1; // out of bounds parameters if (passwordLen == 0 ) passwordLen = 1; if(algorithm != kCCPBKDF2) return -1; if((password = malloc(passwordLen)) == NULL) return -1; for(i=0; i<passwordLen; i++) password[i] = 'a'; if((salt = malloc(saltLen)) == NULL) return -1; for(i=0; i<saltLen; i++) salt[i] = i%256; if((derivedKey = malloc(derivedKeyLen)) == NULL) return -1; for(elapsedTime = 0, i=0; i < 5 && elapsedTime == 0; i++) { startTime = timer(); if(CCKeyDerivationPBKDF(algorithm, password, passwordLen, salt, saltLen, prf, ROUNDMEASURE, derivedKey, derivedKeyLen)) return -2; endTime = timer(); elapsedTime = endTime - startTime; } if(elapsedTime == 0) return 123456; // arbitrary, but something is seriously wrong free(password); free(salt); free(derivedKey); return (msec * ROUNDMEASURE)/elapsedTime; }
int CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen, const uint8_t *salt, size_t saltLen, CCPseudoRandomAlgorithm prf, uint rounds, uint8_t *derivedKey, size_t derivedKeyLen) { const struct ccdigest_info *di; CC_DEBUG_LOG(ASL_LEVEL_ERR, "PasswordLen %lu SaltLen %lU PRF %d Rounds %u DKLen %lu\n", passwordLen, saltLen, prf, rounds, derivedKeyLen); if(algorithm != kCCPBKDF2) return -1; switch(prf) { case kCCPRFHmacAlgSHA1: di = CCDigestGetDigestInfo(kCCDigestSHA1); break; case kCCPRFHmacAlgSHA224: di = CCDigestGetDigestInfo(kCCDigestSHA224); break; case kCCPRFHmacAlgSHA256: di = CCDigestGetDigestInfo(kCCDigestSHA256); break; case kCCPRFHmacAlgSHA384: di = CCDigestGetDigestInfo(kCCDigestSHA384); break; case kCCPRFHmacAlgSHA512: di = CCDigestGetDigestInfo(kCCDigestSHA512); break; default: return -1; } if(!password || !salt || !derivedKey || (derivedKeyLen == 0) || (rounds == 0)) return -1; ccpbkdf2_hmac(di, passwordLen, password, saltLen, salt, rounds, derivedKeyLen, derivedKey); return 0; }
void CCRSACryptorRelease(CCRSACryptorRef key) { CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); ccRSACryptorClear(key); }
CCCryptorStatus CCRSACryptorCreatePairFromData(uint32_t e, uint8_t *xp1, size_t xp1Length, uint8_t *xp2, size_t xp2Length, uint8_t *xp, size_t xpLength, uint8_t *xq1, size_t xq1Length, uint8_t *xq2, size_t xq2Length, uint8_t *xq, size_t xqLength, CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey, uint8_t *retp, size_t *retpLength, uint8_t *retq, size_t *retqLength, uint8_t *retm, size_t *retmLength, uint8_t *retd, size_t *retdLength) { CCCryptorStatus retval; CCRSACryptor *privateCryptor = NULL; CCRSACryptor *publicCryptor = NULL; cc_unit x_p1[ccn_nof_size(xp1Length)]; cc_unit x_p2[ccn_nof_size(xp2Length)]; cc_unit x_p[ccn_nof_size(xpLength)]; cc_unit x_q1[ccn_nof_size(xq1Length)]; cc_unit x_q2[ccn_nof_size(xq2Length)]; cc_unit x_q[ccn_nof_size(xqLength)]; cc_unit e_value[1]; size_t nbits = xpLength * 8 + xqLength * 8; // or we'll add this as a parameter. This appears to be correct for FIPS cc_size n = ccn_nof(nbits); cc_unit p[n], q[n], m[n], d[n]; cc_size np, nq, nm, nd; np = nq = nm = nd = n; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); e_value[0] = (cc_unit) e; __Require_Action((privateCryptor = ccMallocRSACryptor(nbits, ccRSAKeyPrivate)) != NULL, errOut, retval = kCCMemoryFailure); __Require_Action(ccn_read_uint(ccn_nof_size(xp1Length), x_p1, xp1Length, xp1) == 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(ccn_nof_size(xp2Length), x_p2, xp2Length, xp2)== 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(ccn_nof_size(xpLength), x_p, xpLength, xp) == 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(ccn_nof_size(xq1Length), x_q1, xq1Length, xq1) == 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(ccn_nof_size(xq2Length), x_q2, xq2Length, xq2) == 0, errOut, retval = kCCParamError); __Require_Action(ccn_read_uint(ccn_nof_size(xqLength), x_q, xqLength, xq) == 0, errOut, retval = kCCParamError); __Require_Action(ccrsa_make_931_key(nbits, 1, e_value, ccn_nof_size(xp1Length), x_p1, ccn_nof_size(xp2Length), x_p2, ccn_nof_size(xpLength), x_p, ccn_nof_size(xq1Length), x_q1, ccn_nof_size(xq2Length), x_q2, ccn_nof_size(xqLength), x_q, privateCryptor->fk, &np, p, &nq, q, &nm, m, &nd, d) == 0, errOut, retval = kCCDecodeError); privateCryptor->keyType = ccRSAKeyPrivate; __Require_Action((publicCryptor = CCRSACryptorGetPublicKeyFromPrivateKey(privateCryptor)) != NULL, errOut, retval = kCCMemoryFailure); *publicKey = publicCryptor; *privateKey = privateCryptor; ccn_write_arg(np, p, retp, retpLength); ccn_write_arg(nq, q, retq, retqLength); ccn_write_arg(nm, m, retm, retmLength); ccn_write_arg(nd, d, retd, retdLength); return kCCSuccess; errOut: if(privateCryptor) ccRSACryptorClear(privateCryptor); if(publicCryptor) ccRSACryptorClear(publicCryptor); // CLEAR the bits *publicKey = *privateKey = NULL; return retval; }