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 CCRSACryptorEncrypt(CCRSACryptorRef publicKey, CCAsymmetricPadding padding, const void *plainText, size_t plainTextLen, void *cipherText, size_t *cipherTextLen, const void *tagData, size_t tagDataLen, CCDigestAlgorithm digestType) { CCCryptorStatus retval = kCCSuccess; CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n"); if(!publicKey || !cipherText || !plainText || !cipherTextLen) return kCCParamError; switch(padding) { case ccPKCS1Padding: if(ccrsa_encrypt_eme_pkcs1v15(ccrsa_ctx_public(publicKey->fk), ccDRBGGetRngState(), cipherTextLen, cipherText, plainTextLen, (uint8_t *) plainText) != 0) retval = kCCDecodeError; break; case ccOAEPPadding: if(ccrsa_encrypt_oaep(ccrsa_ctx_public(publicKey->fk), CCDigestGetDigestInfo(digestType), ccDRBGGetRngState(), cipherTextLen, cipherText, plainTextLen, (uint8_t *) plainText, tagDataLen, tagData) != 0) retval = kCCDecodeError; break; default: retval = kCCParamError; goto errOut; } errOut: return retval; }
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 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 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; }
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; }
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; }
static OSStatus SecRSAPublicKeyInit(SecKeyRef key, const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) { OSStatus result = errSecParam; ccrsa_pub_ctx_t pubkey; pubkey.pub = key->key; // Set maximum size for parsers ccrsa_ctx_n(pubkey) = ccn_nof(kMaximumRSAKeyBits); switch (encoding) { case kSecKeyEncodingBytes: // Octets is PKCS1 case kSecKeyEncodingPkcs1: result = ccrsa_pub_decode(pubkey, keyDataLength, keyData); break; case kSecKeyEncodingApplePkcs1: result = ccrsa_pub_decode_apple(pubkey, keyDataLength, keyData); break; case kSecKeyEncodingRSAPublicParams: { SecRSAPublicKeyParams *params = (SecRSAPublicKeyParams *)keyData; require_noerr(ccrsa_pub_init(pubkey, params->modulusLength, params->modulus, params->exponentLength, params->exponent), errOut); result = errSecSuccess; break; } case kSecExtractPublicFromPrivate: { ccrsa_full_ctx_t fullKey; fullKey.full = (ccrsa_full_ctx*) keyData; cc_size fullKeyN = ccrsa_ctx_n(fullKey); require(fullKeyN <= ccrsa_ctx_n(pubkey), errOut); memcpy(pubkey.pub, ccrsa_ctx_public(fullKey).pub, ccrsa_pub_ctx_size(ccn_sizeof_n(fullKeyN))); result = errSecSuccess; break; } default: break; } errOut: return result; }
static int RSA_POST() { int result = -1; uint32_t uintEValue = 3; // xp1 = 1384167f9844865eae22cb3672 unsigned char* xp1Data = (unsigned char*)"\x13\x84\x16\x7f\x98\x44\x86\x5e\xae\x22\xcb\x36\x72"; size_t xp1DataSize = 13; // xp2 = 1a085b0b737f842a8a1f32b662 unsigned char* xp2Data = (unsigned char*)"\x1a\x08\x5b\x0b\x73\x7f\x84\x2a\x8a\x1f\x32\xb6\x62"; size_t xp2DataSize = 13; // Xp = beef5ad133e9a3955097c8d8b03bd50662b5f82b8e9c3eab5c8d9d3311c337ef7ce8ddfe902bd2235293d2bdf69353f944de0b46417cb2090c1e099206af1b4 unsigned char* xpData = (unsigned char*)"\xbe\xef\x5a\xd1\x33\xe9\xa3\x95\x50\x97\xc8\xd8\xb0\x3b\xd5\x06\x62\xb5\xf8\x2b\x8e\x9c\x3e\xab\x5c\x8d\x9d\x33\x11\xc3\x37\xef\x7c\xe8\xdd\xfe\x90\x2b\xd2\x23\x52\x93\xd2\xbd\xf6\x93\x53\xf9\x44\xde\x0b\x46\x41\x7c\xb2\x09\x0c\x1e\x09\x92\x06\xaf\x1b\x04"; size_t xpDataSize = 64; // xq1 = 17fa0d7d2189c759b0b8eb1d18 unsigned char* xq1Data = (unsigned char*)"\x17\xfa\x0d\x7d\x21\x89\xc7\x59\xb0\xb8\xeb\x1d\x18"; size_t xq1DataSize = 13; // xq2 = 17c8e735fb8d58e13a412ae214 unsigned char* xq2Data = (unsigned char*)"\x17\xc8\xe7\x35\xfb\x8d\x58\xe1\x3a\x41\x2a\xe2\x14"; size_t xq2DataSize = 13; // Xq = f2d7b992fb914cd677876bb3702b1441716ebd2b447c3a0500a6e0e0449feb1cbdec1d7eee96a88230224ef3f7c2c7b858cd63f1c86df0432798de6ffd41a12a unsigned char* xqData = (unsigned char*)"\xf2\xd7\xb9\x92\xfb\x91\x4c\xd6\x77\x87\x6b\xb3\x70\x2b\x14\x41\x71\x6e\xbd\x2b\x44\x7c\x3a\x05\x00\xa6\xe0\xe0\x44\x9f\xeb\x1c\xbd\xec\x1d\x7e\xee\x96\xa8\x82\x30\x22\x4e\xf3\xf7\xc2\xc7\xb8\x58\xcd\x63\xf1\xc8\x6d\xf0\x43\x27\x98\xde\x6f\xfd\x41\xa1\x2a"; size_t xqDataSize = 64; cc_unit x_p1[ccn_nof_size(xp1DataSize)]; cc_unit x_p2[ccn_nof_size(xp2DataSize)]; cc_unit x_p[ccn_nof_size(xpDataSize)]; cc_unit x_q1[ccn_nof_size(xq1DataSize)]; cc_unit x_q2[ccn_nof_size(xq2DataSize)]; cc_unit x_q[ccn_nof_size(xqDataSize)]; cc_unit e_value[1]; size_t nbits = xpDataSize * 8 + xqDataSize * 8; // or we'll add this as a parameter. This appears to be correct for FIPS cc_size n = ccn_nof(nbits); e_value[0] = (cc_unit)uintEValue; if (0 != ccn_read_uint(ccn_nof_size(xp1DataSize), x_p1, xp1DataSize, xp1Data)) { return result; } if (0 != ccn_read_uint(ccn_nof_size(xp2DataSize), x_p2, xp2DataSize, xp2Data)) { return result; } if (0 != ccn_read_uint(ccn_nof_size(xpDataSize), x_p, xpDataSize, xpData)) { return result; } if (0 != ccn_read_uint(ccn_nof_size(xq1DataSize), x_q1, xq1DataSize, xq1Data)) { return result; } if (0 != ccn_read_uint(ccn_nof_size(xq2DataSize), x_q2, xq2DataSize, xq2Data)) { return result; } if (0 != ccn_read_uint(ccn_nof_size(xqDataSize), x_q, xqDataSize, xqData)) { return result; }; cc_size np = n; cc_size nq = n; cc_size nm = n; cc_size nd = n; cc_unit p[n]; cc_unit q[n]; cc_unit m[n]; cc_unit d[n]; ccrsa_full_ctx_decl(ccn_sizeof_n(n), full_key); ccrsa_ctx_n(full_key) = n; if (0 != ccrsa_make_931_key(nbits, 1, e_value, ccn_nof_size(xp1DataSize), x_p1, ccn_nof_size(xp2DataSize), x_p2, ccn_nof_size(xpDataSize), x_p, ccn_nof_size(xq1DataSize), x_q1, ccn_nof_size(xq2DataSize), x_q2, ccn_nof_size(xqDataSize), x_q, full_key, &np, p, &nq, q, &nm, m, &nd, d)) { ccrsa_full_ctx_clear(ccn_sizeof(nbits), full_key); return result; } ccrsa_full_ctx *fk = full_key; ccrsa_pub_ctx_t pub_key = ccrsa_ctx_public(fk); unsigned char fake_digest[20]; memcpy(fake_digest, "ABCEDFGHIJKLMNOPRSTU", 20); uint8_t sig[(nbits+7)/8]; size_t siglen=sizeof(sig); if (0 != ccrsa_sign_pkcs1v15(full_key, ccoid_sha1, CCSHA1_OUTPUT_SIZE, fake_digest, &siglen, sig)) { ccrsa_full_ctx_clear(ccn_sizeof(nbits), full_key); return result; } bool ok; if (0 != ccrsa_verify_pkcs1v15(pub_key, ccoid_sha1, CCSHA1_OUTPUT_SIZE, fake_digest, siglen, sig, &ok) || !ok) { ccrsa_full_ctx_clear(ccn_sizeof(nbits), full_key); return result; } return 0; }