/* siglen will be the actual lenght of the prime in bytes */ int ccrsa_sign_pkcs1v15(ccrsa_full_ctx_t key, const uint8_t *oid, size_t digest_len, const uint8_t *digest, size_t *sig_len, uint8_t *sig) { size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(key), ccrsa_ctx_m(key)); cc_size n=ccrsa_ctx_n(key); cc_unit s[n]; int err; if(*sig_len<m_size) return CCRSA_INVALID_INPUT; *sig_len=m_size; err=ccrsa_emsa_pkcs1v15_encode(m_size, sig, digest_len, digest, oid); if(err) return err; ccn_read_uint(n, s, m_size, sig); err=ccrsa_priv_crypt(ccrsa_ctx_private(key), s, s); if(err) return err; /* we need to write leading zeroes if necessary */ ccn_write_uint_padded(n, s, m_size, sig); return 0; }
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; }
/* siglen will be the actual lenght of the prime in bytes */ int ccrsa_sign_oaep(ccrsa_full_ctx_t key, const struct ccdigest_info* di, struct ccrng_state *rng, size_t digest_len, const uint8_t *digest, size_t *sig_len, uint8_t *sig) { size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(key), ccrsa_ctx_m(key)); cc_size n=ccrsa_ctx_n(key); cc_unit s[n]; int err; if(*sig_len<m_size) return CCRSA_INVALID_INPUT; *sig_len=m_size; err=ccrsa_oaep_encode(di, rng, m_size, s, digest_len, digest); if(err) return err; err=ccrsa_priv_crypt(ccrsa_ctx_private(key), s, s); if(err) return err; /* we need to write leading zeroes if necessary */ ccn_write_uint_padded(n, s, m_size, sig); return 0; }
int ccrsa_decrypt_oaep(ccrsa_full_ctx_t key, const struct ccdigest_info* di, size_t *r_size, uint8_t *r, size_t c_size, uint8_t *c, size_t parameter_data_len, const uint8_t *parameter_data) { size_t m_size = ccrsa_block_size(key); cc_size n=ccrsa_ctx_n(key); cc_unit tmp[n]; int err; // Sanity check if (m_size<di->output_size*2+1) { return CCRSA_INVALID_CONFIG; } // Output buffer is too small if(*r_size<m_size-di->output_size*2+2) { return CCRSA_INVALID_INPUT; } // The ciphertext does not match the expected size if ((c_size<m_size) || (ccn_read_uint(n, tmp, c_size, c))) { return CCRSA_INVALID_INPUT; } // RSA decryption if ((err = ccrsa_priv_crypt(ccrsa_ctx_private(key), tmp, tmp)) == 0) { // Padding decoding err = ccrsa_oaep_decode_parameter(di, r_size, r, m_size, tmp, parameter_data_len, parameter_data); } return err; }
int ccrsa_decrypt_eme_pkcs1v15(ccrsa_full_ctx_t key, size_t *r_size, uint8_t *r, size_t s_size, uint8_t *s) { size_t m_size = ccrsa_block_size(key); cc_size n=ccrsa_ctx_n(key); cc_unit tmp[n]; int err; if(*r_size<m_size) return CCRSA_INVALID_INPUT; *r_size=m_size; if(ccn_read_uint(n, tmp, s_size, s)) return CCRSA_INVALID_INPUT; // RSA decryption if ((err = ccrsa_priv_crypt(ccrsa_ctx_private(key), tmp, tmp)) == 0) { // Padding decoding err = ccrsa_eme_pkcs1v15_decode(r_size, r, m_size, tmp); } return err; }
static OSStatus SecRSAPrivateKeyRawDecrypt(SecKeyRef key, SecPadding padding, const uint8_t *cipherText, size_t cipherTextLen, uint8_t *plainText, size_t *plainTextLen) { OSStatus result = errSSLCrypto; ccrsa_full_ctx_t fullkey; fullkey.full = key->key; size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey)); cc_unit s[ccrsa_ctx_n(fullkey)]; uint8_t recoveredData[ccn_sizeof_n(ccrsa_ctx_n(fullkey))]; ccn_read_uint(ccrsa_ctx_n(fullkey), s, cipherTextLen, cipherText); ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s); const uint8_t* sBytes = (uint8_t*) s; const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(fullkey)); require(plainTextLen, errOut); switch (padding) { case kSecPaddingNone: ccn_swap(ccrsa_ctx_n(fullkey), s); // Skip Zeros since our contract is to do so. while (sBytes < sEnd && *sBytes == 0x00) ++sBytes; break; case kSecPaddingPKCS1: { ccn_swap(ccrsa_ctx_n(fullkey), s); // Verify and skip PKCS1 padding: // // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData // size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size; while (prefix_zeros--) require_quiet(*sBytes++ == 0x00, errOut); require_quiet(*sBytes++ == 0x00, errOut); require_quiet(*sBytes++ == RSA_PKCS1_PAD_ENCRYPT, errOut); while (*sBytes != 0x00) { require_quiet(++sBytes < sEnd, errOut); } // Required to have at least 8 non-zeros require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut); require_quiet(*sBytes == 0x00, errOut); require_quiet(++sBytes < sEnd, errOut); break; } case kSecPaddingOAEP: { size_t length = sizeof(recoveredData); require_noerr_quiet(ccrsa_oaep_decode(ccsha1_di(), ccn_write_uint_size(ccrsa_ctx_n(fullkey),ccrsa_ctx_m(fullkey)), s, &length, recoveredData), errOut); sBytes = recoveredData; sEnd = recoveredData + length; break; } default: goto errOut; } require((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut); *plainTextLen = sEnd - sBytes; memcpy(plainText, sBytes, *plainTextLen); result = errSecSuccess; errOut: bzero(recoveredData, sizeof(recoveredData)); ccn_zero(ccrsa_ctx_n(fullkey), s); return result; }
static OSStatus SecRSAPrivateKeyRawSign(SecKeyRef key, SecPadding padding, const uint8_t *dataToSign, size_t dataToSignLen, uint8_t *sig, size_t *sigLen) { OSStatus result = errSecParam; ccrsa_full_ctx_t fullkey; fullkey.full = key->key; size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey)); cc_unit s[ccrsa_ctx_n(fullkey)]; uint8_t* sBytes = (uint8_t*) s; require(sigLen, errOut); require(*sigLen >= m_size, errOut); switch (padding) { case kSecPaddingNone: require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(fullkey), s, dataToSignLen, dataToSign), errOut); require_quiet(ccn_cmp(ccrsa_ctx_n(fullkey), s, ccrsa_ctx_m(fullkey)) < 0, errOut); break; case kSecPaddingPKCS1: { // Create PKCS1 padding: // // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData // const int kMinimumPadding = 1 + 1 + 8 + 1; require(dataToSignLen < m_size - kMinimumPadding, errOut); size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(fullkey)) - m_size; while (prefix_zeros--) *sBytes++ = 0x00; size_t pad_size = m_size - dataToSignLen; *sBytes++ = 0x00; *sBytes++ = RSA_PKCS1_PAD_SIGN; size_t ff_size; for(ff_size = pad_size - 3; ff_size > 0; --ff_size) *sBytes++ = 0xFF; *sBytes++ = 0x00; // Get the user data into s looking like a ccn. memcpy(sBytes, dataToSign, dataToSignLen); ccn_swap(ccrsa_ctx_n(fullkey), s); break; } case kSecPaddingOAEP: result = errSecParam; default: goto errOut; } ccrsa_priv_crypt(ccrsa_ctx_private(fullkey), s, s); // Pad with leading zeros to fit in modulus size ccn_write_uint_padded(ccrsa_ctx_n(fullkey), s, m_size, sig); *sigLen = m_size; result = errSecSuccess; errOut: ccn_zero(ccrsa_ctx_n(fullkey), s); return result; }