int ccrsa_verify_pkcs1v15(ccrsa_pub_ctx_t key, const uint8_t *oid,
                          size_t digest_len, const uint8_t *digest,
                          size_t sig_len, const uint8_t *sig,
                          bool *valid)
{
    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];
    *valid = false;
    int err;

    cc_require_action(sig_len==m_size,errOut,err=CCRSA_INVALID_INPUT);

    ccn_read_uint(n, s, sig_len, sig);
    cc_require((err=ccrsa_pub_crypt(key, s, s))==0,errOut);

    {
        unsigned char em[m_size];
        ccn_write_uint_padded(n, s, m_size, em);
    
#ifdef VERIFY_BY_ENCODE_THEN_MEMCMP
        unsigned char em2[m_size];
   
        cc_require((err=ccrsa_emsa_pkcs1v15_encode(m_size, em2, digest_len, digest, oid))==0,errOut); /* digest len is too big ?*/

        if(memcmp(em, em2, m_size)==0)
            *valid = true;
#else
        if(ccrsa_emsa_pkcs1v15_verify(m_size, em, digest_len, digest, oid)==0)
            *valid = true;
#endif
    }
errOut:
    return err;
}
static CFDataRef SecRSAPublicKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_pub_ctx_t pubkey)
{
    size_t m_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
    size_t e_size = ccn_write_int_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));

    const size_t seq_size = DERLengthOfItem(ASN1_INTEGER, m_size) +
                            DERLengthOfItem(ASN1_INTEGER, e_size);

    const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);

	CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);

    if (pkcs1 == NULL)
        return NULL;

	CFDataSetLength(pkcs1, result_size);

    uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);

    *bytes++ = ASN1_CONSTR_SEQUENCE;

    DERSize itemLength = 4;
    DEREncodeLength(seq_size, bytes, &itemLength);
    bytes += itemLength;

    ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, &bytes);
    ccasn_encode_int(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey), e_size, &bytes);

    return pkcs1;
}
Exemple #3
0
/* 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;
}
/* 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;
}
void ccrsa_dump_public_key(ccrsa_pub_ctx_t key) {
    ccn_cprint(ccrsa_ctx_n(key),      "uint8_t m[]  = ", ccrsa_ctx_m(key));
    ccn_cprint(ccrsa_ctx_n(key) + 1,  "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key)));
    ccn_cprint(ccrsa_ctx_n(key),      "uint8_t e[]  = ", ccrsa_ctx_e(key));

    printf("--\n");
}
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;
}
Exemple #7
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;
}
//
// pubkey is initilaized with an n which is the maximum it can hold
// We set the n to its correct value given m.
//
static int ccrsa_pub_init(ccrsa_pub_ctx_t pubkey,
                          size_t m_size, const uint8_t* m,
                          size_t e_size, const uint8_t* e)
{
    cc_skip_zeros(m_size, m);

    cc_size nm = ccn_nof_size(m_size);
    if (nm > ccrsa_ctx_n(pubkey))
        return -1;

    ccrsa_ctx_n(pubkey) = nm;

    ccn_read_uint(nm, ccrsa_ctx_m(pubkey), m_size, m);
    cczp_init(ccrsa_ctx_zm(pubkey));

    return ccn_read_uint(nm, ccrsa_ctx_e(pubkey), e_size, e);
}
CFDataRef SecKeyCopyExponent(SecKeyRef key) {
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    size_t e_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_e(pubkey));

	CFAllocatorRef allocator = CFGetAllocator(key);
	CFMutableDataRef exponentData = CFDataCreateMutable(allocator, e_size);

    if (exponentData == NULL)
        return NULL;

	CFDataSetLength(exponentData, e_size);

    ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), e_size, CFDataGetMutableBytePtr(exponentData));

    return exponentData;
}
CFDataRef SecKeyCopyModulus(SecKeyRef key) {
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));

	CFAllocatorRef allocator = CFGetAllocator(key);
	CFMutableDataRef modulusData = CFDataCreateMutable(allocator, m_size);

    if (modulusData == NULL)
        return NULL;

	CFDataSetLength(modulusData, m_size);

    ccn_write_uint(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey), m_size, CFDataGetMutableBytePtr(modulusData));

    return modulusData;
}
Exemple #11
0
static CCRSACryptor *
ccMallocRSACryptor(size_t nbits, CCRSAKeyType keyType)
{
    CCRSACryptor *retval;
    cc_size n = ccn_nof(nbits);
    if((retval = CC_XMALLOC(sizeof(CCRSACryptor))) == NULL) return NULL;
    retval->keySize = nbits;
    ccrsa_ctx_n(retval->fk) = n;
    return retval;
}
Exemple #12
0
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 ccrsa_full_decode(ccrsa_full_ctx_t fullkey, size_t pkcs1_size, const uint8_t* pkcs1)
{
    OSStatus result = errSecParam;

	DERItem keyItem = {(DERByte *)pkcs1, pkcs1_size};
    DERRSAKeyPair decodedKey;

	require_noerr_action(DERParseSequence(&keyItem,
                                          DERNumRSAKeyPairItemSpecs, DERRSAKeyPairItemSpecs,
                                          &decodedKey, sizeof(decodedKey)),
                         errOut, result = errSecDecode);

    require_noerr(ccrsa_pub_init(fullkey,
                                 decodedKey.n.length, decodedKey.n.data,
                                 decodedKey.e.length, decodedKey.e.data),
                  errOut);
    ccn_read_uint(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey),
                  decodedKey.d.length, decodedKey.d.data);
    {
        ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);
        CCZP_N(ccrsa_ctx_private_zp(privkey)) = ccn_nof((ccn_bitsof_n(ccrsa_ctx_n(fullkey)) / 2) + 1);
        CCZP_N(ccrsa_ctx_private_zq(privkey)) = cczp_n(ccrsa_ctx_private_zp(privkey));

        // TODO: Actually remember decodedKey.d.

        require_noerr(ccrsa_priv_init(privkey,
                                     decodedKey.p.length, decodedKey.p.data,
                                      decodedKey.q.length, decodedKey.q.data,
                                      decodedKey.dp.length, decodedKey.dp.data,
                                      decodedKey.dq.length, decodedKey.dq.data,
                                      decodedKey.qInv.length, decodedKey.qInv.data),
                      errOut);
    }

    result = errSecSuccess;

errOut:
    return result;
}
Exemple #14
0
// verify the signature in sig. The original (hash of the message) message is in digest
int ccrsa_verify_pss(ccrsa_pub_ctx_t key,
                      const struct ccdigest_info* di, const struct ccdigest_info* MgfDi,
                      size_t digestSize, const uint8_t *digest,
                      size_t sigSize, const uint8_t *sig,
                      size_t saltSize, bool *valid)
{
    const cc_size modBits =ccn_bitlen(ccrsa_ctx_n(key), ccrsa_ctx_m(key));
    const cc_size modBytes = cc_ceiling(modBits, 8);
    const cc_size emBits = modBits-1; //as defined in §8.1.1
    const cc_size emSize = cc_ceiling(emBits, 8);
    *valid = false;
    int rc=0;
    
    //1.
    if(modBytes!= sigSize)  return CCRSA_INVALID_INPUT;
    if(digestSize !=  di->output_size) return CCRSA_INVALID_INPUT;

    //2.
    const cc_size modWords=ccrsa_ctx_n(key);
    cc_unit EM[modWords];  //EM islarge enough to fit sig variable
    
    //2.a read sig to tmp array and make sure it fits
    cc_require_action(ccn_read_uint(modWords, EM, sigSize, sig)==0,errOut,rc=CCRSA_INVALID_INPUT);

    //2.b
    cc_require((rc=ccrsa_pub_crypt(key, EM, EM))==0,errOut);
    
    //2.c
    ccn_swap(modWords, EM);

    //3
    const size_t ofs = modWords*sizeof(cc_unit)-emSize;
    cc_assert(ofs<=sizeof(cc_unit)); //make sure sizes are consistent and we don't overrun buffers.
    rc|= ccrsa_emsa_pss_decode(di, MgfDi, saltSize, digestSize,  digest, emBits, (uint8_t *) EM+ofs);

    *valid = (rc==0)?true:false;
errOut:
    return rc;
}
void ccrsa_dump_full_key(ccrsa_full_ctx_t key) {
    ccn_cprint(ccrsa_ctx_n(key),      "uint8_t m[]  = ", ccrsa_ctx_m(key));
    ccn_cprint(ccrsa_ctx_n(key) + 1,  "uint8_t rm[] = ", cczp_recip(ccrsa_ctx_zm(key)));
    ccn_cprint(ccrsa_ctx_n(key),      "uint8_t e[]  = ", ccrsa_ctx_e(key));
    ccn_cprint(ccrsa_ctx_n(key),      "uint8_t d[]  = ", ccrsa_ctx_d(key));

    printf("cc_size np = %lu;\n", cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))),     "uint8_t p[]  = ",
               cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))) + 1, "uint8_t rp[] = ",
               cczp_recip(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))));
    printf("cc_size nq = %lu;\n", cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))),     "uint8_t q[]  = ",
               cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))) + 1, "uint8_t rq[] = ",
               cczp_recip(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))),     "uint8_t dp[] = ",
               ccrsa_ctx_private_dp(ccrsa_ctx_private(key)));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))),     "uint8_t dq[] = ",
               ccrsa_ctx_private_dq(ccrsa_ctx_private(key)));
    ccn_cprint(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))),     "uint8_t qinv[] = ",
               ccrsa_ctx_private_qinv(ccrsa_ctx_private(key)));
    printf("--\n");
}
size_t ccder_encode_rsa_priv_size(const ccrsa_full_ctx_t key) {
    ccrsa_priv_ctx_t privk = ccrsa_ctx_private(key);
    cc_size n = ccrsa_ctx_n(key);
	cc_unit version_0[ccn_nof(1)] = {0x00};
	return ccder_sizeof(CCDER_CONSTRUCTED_SEQUENCE,
      ccder_sizeof_integer(ccn_nof(1), version_0) +
      ccder_sizeof_integer(n, ccrsa_ctx_m(key)) +
      ccder_sizeof_integer(n, ccrsa_ctx_e(key)) +
      ccder_sizeof_integer(n, ccrsa_ctx_d(key)) +
      ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), cczp_prime(ccrsa_ctx_private_zp(privk))) +
      ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zq(privk)), cczp_prime(ccrsa_ctx_private_zq(privk))) +
      ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), ccrsa_ctx_private_dp(privk)) +
      ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zq(privk)), ccrsa_ctx_private_dq(privk)) +
      ccder_sizeof_integer(cczp_n(ccrsa_ctx_private_zp(privk)), ccrsa_ctx_private_qinv(privk))
    );
}
static OSStatus SecRSAPrivateKeyInit(SecKeyRef key,
    const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
    OSStatus result = errSecParam;

    ccrsa_full_ctx_t fullkey;
    fullkey.full = key->key;

    // Set maximum size for parsers
    ccrsa_ctx_n(fullkey) = ccn_nof(kMaximumRSAKeyBits);

    switch (encoding) {
        case kSecKeyEncodingBytes: // Octets is PKCS1
        case kSecKeyEncodingPkcs1:
            result = ccrsa_full_decode(fullkey, keyDataLength, keyData);
            break;
        case kSecGenerateKey:
        {
            CFDictionaryRef parameters = (CFDictionaryRef) keyData;

            CFTypeRef ksize = CFDictionaryGetValue(parameters, kSecAttrKeySizeInBits);
            CFIndex keyLengthInBits = getIntValue(ksize);

            if (keyLengthInBits < 256 || keyLengthInBits > kMaximumRSAKeyBits) {
                secwarning("Invalid or missing key size in: %@", parameters);
                return errSecKeySizeNotAllowed;
            }

            /* TODO: Add support for kSecPublicExponent parameter. */
            static uint8_t e[] = { 0x01, 0x00, 0x01 }; // Default is 65537
            if (!ccrsa_generate_key(keyLengthInBits, fullkey.full, sizeof(e), e, ccrng_seckey))
                result = errSecSuccess;
            break;
        }
        default:
            break;
    }

    return result;
}
int ccrsa_get_fullkey_components(const ccrsa_full_ctx_t key, 
                                 uint8_t *modulus, size_t *modulusLength, 
                                 uint8_t *exponent, size_t *exponentLength,
                                 uint8_t *p, size_t *pLength, 
                                 uint8_t *q, size_t *qLength)
{
    cc_size n = ccrsa_ctx_n(key);
    if(ccCoreZP2pointerAndData(cczp_n(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))),
                               cczp_prime(ccrsa_ctx_private_zp(ccrsa_ctx_private(key))),
                               p, pLength )) return -1;
    if(ccCoreZP2pointerAndData(cczp_n(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))),
                               cczp_prime(ccrsa_ctx_private_zq(ccrsa_ctx_private(key))),
                               q, qLength )) return -1;
    if(ccCoreZP2pointerAndData(n,
                               ccrsa_ctx_m(key),
                               modulus, modulusLength )) return -1;
    if(ccCoreZP2pointerAndData(n,
                               ccrsa_ctx_d(key),
                               exponent, exponentLength )) return -1;

    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;
}
Exemple #20
0
int ccrsa_test_verify_pkcs1v15_vector(const struct ccrsa_verify_vector *v)
{
    bool ok;
    int rc;
    const struct ccdigest_info *di = v->di;
    const cc_size n = ccn_nof(v->modlen);
    const size_t s = ccn_sizeof(v->modlen);
    unsigned char H[di->output_size];

    cc_unit exponent[n];
    cc_unit modulus[n];
    ccrsa_pub_ctx_decl(ccn_sizeof(v->modlen), key);
    ccrsa_ctx_n(key) = n;
    ccn_seti(n, exponent, v->exp);
    ccn_read_uint(n, modulus, s, v->mod);

    ccrsa_init_pub(key, modulus, exponent);
    ccdigest(di, v->msglen, v->msg, H);
    rc=ccrsa_verify_pkcs1v15(key, di->oid.oid, di->output_size, H, v->siglen, v->sig, &ok);

    return ((rc==0)
        && ((ok && v->valid) || (!ok && !v->valid)))?0:1;
}
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 SecRSAPublicKeyRawDecrypt(SecKeyRef key, SecPadding padding,
	const uint8_t *cipherText, size_t cipherTextLen, uint8_t *plainText, size_t *plainTextLen) {
    OSStatus result = errSSLCrypto;

    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    cc_unit s[ccrsa_ctx_n(pubkey)];

    require_action_quiet(cipherText != NULL, errOut, result = errSecParam);
    require_action_quiet(plainText != NULL, errOut, result = errSecParam);
    require_action_quiet(plainTextLen != NULL, errOut, result = errSecParam);

    ccn_read_uint(ccrsa_ctx_n(pubkey), s, cipherTextLen, cipherText);
    ccrsa_pub_crypt(pubkey, s, s);
    ccn_swap(ccrsa_ctx_n(pubkey), s);

    const uint8_t* sBytes = (uint8_t*) s;
    const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));

    switch (padding) {
        case kSecPaddingNone:
            // Skip leading zeros
            // We return the bytes for a number and
            // trim leading zeroes
            while (sBytes < sEnd && *sBytes == 0x00)
                ++sBytes;
            break;

        case kSecPaddingPKCS1:
        {
            // Verify and skip PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
            //
            size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - 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 0xFFs
            require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);

            require_quiet(*sBytes == 0x00, errOut);
            require_quiet(++sBytes < sEnd, errOut);

            break;
        }
        case kSecPaddingOAEP:
            result = errSecParam;
        default:
            goto errOut;
    }

    // Return the rest.
    require_action((sEnd - sBytes) <= (ptrdiff_t)*plainTextLen, errOut, result = errSecParam);

    *plainTextLen = sEnd - sBytes;
    memcpy(plainText, sBytes, *plainTextLen);

    result = errSecSuccess;

errOut:
    ccn_zero(ccrsa_ctx_n(pubkey), s);

    return result;
}
static CFDataRef SecRSAPrivateKeyCreatePKCS1(CFAllocatorRef allocator, ccrsa_full_ctx_t fullkey)
{
    ccrsa_priv_ctx_t privkey = ccrsa_ctx_private(fullkey);

    const cc_size np = cczp_n(ccrsa_ctx_private_zp(privkey));
    const cc_size nq = cczp_n(ccrsa_ctx_private_zq(privkey));

    size_t m_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
    size_t e_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey));
    size_t d_size = ccn_write_int_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey));

    size_t p_size = ccn_write_int_size(np, cczp_prime(ccrsa_ctx_private_zp(privkey)));
    size_t q_size = ccn_write_int_size(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)));

    size_t dp_size = ccn_write_int_size(np, ccrsa_ctx_private_dp(privkey));
    size_t dq_size = ccn_write_int_size(nq, ccrsa_ctx_private_dq(privkey));

    size_t qinv_size = ccn_write_int_size(np, ccrsa_ctx_private_qinv(privkey));

    const size_t seq_size = 3 +
                            DERLengthOfItem(ASN1_INTEGER, m_size) +
                            DERLengthOfItem(ASN1_INTEGER, e_size) +
                            DERLengthOfItem(ASN1_INTEGER, d_size) +
                            DERLengthOfItem(ASN1_INTEGER, p_size) +
                            DERLengthOfItem(ASN1_INTEGER, q_size) +
                            DERLengthOfItem(ASN1_INTEGER, dp_size) +
                            DERLengthOfItem(ASN1_INTEGER, dq_size) +
                            DERLengthOfItem(ASN1_INTEGER, qinv_size);

    const size_t result_size = DERLengthOfItem(ASN1_SEQUENCE, seq_size);

	CFMutableDataRef pkcs1 = CFDataCreateMutable(allocator, result_size);

    if (pkcs1 == NULL)
        return NULL;

	CFDataSetLength(pkcs1, result_size);

    uint8_t *bytes = CFDataGetMutableBytePtr(pkcs1);

    *bytes++ = ASN1_CONSTR_SEQUENCE;

    DERSize itemLength = 4;
    DEREncodeLength(seq_size, bytes, &itemLength);
    bytes += itemLength;

    *bytes++ = ASN1_INTEGER;
    *bytes++ = 0x01;
    *bytes++ = 0x00;

    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey), m_size, &bytes);
    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_e(fullkey), e_size, &bytes);
    ccasn_encode_int(ccrsa_ctx_n(fullkey), ccrsa_ctx_d(fullkey), d_size, &bytes);

    ccasn_encode_int(np, cczp_prime(ccrsa_ctx_private_zp(privkey)), p_size, &bytes);
    ccasn_encode_int(nq, cczp_prime(ccrsa_ctx_private_zq(privkey)), q_size, &bytes);
    ccasn_encode_int(np, ccrsa_ctx_private_dp(privkey), dp_size, &bytes);
    ccasn_encode_int(nq, ccrsa_ctx_private_dq(privkey), dq_size, &bytes);
    ccasn_encode_int(np, ccrsa_ctx_private_qinv(privkey), qinv_size, &bytes);

    return pkcs1;
}
static size_t SecRSAPrivateKeyBlockSize(SecKeyRef key) {
    ccrsa_full_ctx_t fullkey;
    fullkey.full = key->key;

    return ccn_write_uint_size(ccrsa_ctx_n(fullkey), ccrsa_ctx_m(fullkey));
}
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;
}
static OSStatus SecRSAPublicKeyRawVerify(SecKeyRef key, SecPadding padding,
    const uint8_t *signedData, size_t signedDataLen,
    const uint8_t *sig, size_t sigLen) {
    OSStatus result = errSSLCrypto;

    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    cc_unit s[ccrsa_ctx_n(pubkey)];

    ccn_read_uint(ccrsa_ctx_n(pubkey), s, sigLen, sig);
    ccrsa_pub_crypt(pubkey, s, s);
    ccn_swap(ccrsa_ctx_n(pubkey), s);

    const uint8_t* sBytes = (uint8_t*) s;
    const uint8_t* sEnd = (uint8_t*) (s + ccrsa_ctx_n(pubkey));

    switch (padding) {
        case kSecPaddingNone:
            // Skip leading zeros as long as s is bigger than signedData.
            while (((ptrdiff_t)signedDataLen < (sEnd - sBytes)) && (*sBytes == 0))
                ++sBytes;
            break;

        case kSecPaddingPKCS1:
        {
            // Verify and skip PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_SIGN), 0xFF .. 0x00, signedData
            //
            size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
            
            while (prefix_zeros--)
                require_quiet(*sBytes++ == 0x00, errOut);

            require_quiet(*sBytes++ == 0x00, errOut);
            require_quiet(*sBytes++ == RSA_PKCS1_PAD_SIGN, errOut);

            while (*sBytes == 0xFF) {
                require_quiet(++sBytes < sEnd, errOut);
            }
            // Required to have at least 8 0xFFs
            require_quiet((sBytes - (uint8_t*)s) - 2 >= 8, errOut);

            require_quiet(*sBytes == 0x00, errOut);
            require_quiet(++sBytes < sEnd, errOut);
            break;
        }
        case kSecPaddingOAEP:
            result = errSecParam;
            goto errOut;

        default:
            result = errSecUnimplemented;
            goto errOut;
    }

    // Compare the rest.
    require_quiet((sEnd - sBytes) == (ptrdiff_t)signedDataLen, errOut);
    require_quiet(memcmp(sBytes, signedData, signedDataLen) == 0, errOut);

    result = errSecSuccess;

errOut:
    cc_zero(ccrsa_ctx_n(pubkey), s);

    return result;
}
static OSStatus SecRSAPublicKeyRawEncrypt(SecKeyRef key, SecPadding padding,
    const uint8_t *plainText, size_t plainTextLen,
	uint8_t *cipherText, size_t *cipherTextLen) {
    OSStatus result = errSecParam;
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    cc_unit s[ccrsa_ctx_n(pubkey)];
    const size_t m_size = ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));

    require(cipherTextLen, errOut);
    require(*cipherTextLen >= m_size, errOut);

    uint8_t* sBytes = (uint8_t*) s;

    switch (padding) {
        case kSecPaddingNone:
            require_noerr_quiet(ccn_read_uint(ccrsa_ctx_n(pubkey), s, plainTextLen, plainText), errOut);
            require_quiet(ccn_cmp(ccrsa_ctx_n(pubkey), s, ccrsa_ctx_m(pubkey)) < 0, errOut);
            break;

        case kSecPaddingPKCS1:
        {
            // Create PKCS1 padding:
            //
            // 0x00, 0x01 (RSA_PKCS1_PAD_ENCRYPT), 0xFF .. 0x00, signedData
            //
            const int kMinimumPadding = 1 + 1 + 8 + 1;

            require_quiet(plainTextLen < m_size - kMinimumPadding, errOut);

            size_t prefix_zeros = ccn_sizeof_n(ccrsa_ctx_n(pubkey)) - m_size;
            
            while (prefix_zeros--)
                 *sBytes++ = 0x00;

           size_t pad_size = m_size - plainTextLen;

            *sBytes++ = 0x00;
            *sBytes++ = RSA_PKCS1_PAD_ENCRYPT;

            ccrng_generate(ccrng_seckey, pad_size - 3, sBytes);
            // Remove zeroes from the random pad

            const uint8_t* sEndOfPad = sBytes + (pad_size - 3);
            while (sBytes < sEndOfPad)
            {
                if (*sBytes == 0x00)
                    *sBytes = 0xFF; // Michael said 0xFF was good enough.

                ++sBytes;
            }

            *sBytes++ = 0x00;

            memcpy(sBytes, plainText, plainTextLen);

            ccn_swap(ccrsa_ctx_n(pubkey), s);
            break;
        }
        case kSecPaddingOAEP:
        {
            const struct ccdigest_info* di = ccsha1_di();

            const size_t encodingOverhead = 2 + 2 * di->output_size;

            require_action(m_size > encodingOverhead, errOut, result = errSecParam);
            require_action_quiet(plainTextLen < m_size - encodingOverhead, errOut, result = errSSLCrypto);

            require_noerr_action(ccrsa_oaep_encode(di,
                                                   ccrng_seckey,
                                                   m_size, s,
                                                   plainTextLen, plainText), errOut, result = errSecInternal);
           break;
        }
        default:
            goto errOut;
    }


    ccrsa_pub_crypt(pubkey, s, s);

    ccn_write_uint_padded(ccrsa_ctx_n(pubkey), s, m_size, cipherText);
    *cipherTextLen = m_size;

    result = errSecSuccess;

errOut:
    ccn_zero(ccrsa_ctx_n(pubkey), s);
    return result;
}
/* Private key static functions. */
static void SecRSAPrivateKeyDestroy(SecKeyRef key) {
    /* Zero out the public key */
    ccrsa_full_ctx_t fullkey;
    fullkey.full = key->key;
    cc_zero(ccrsa_full_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(fullkey))), fullkey.full);
}
static size_t SecRSAPublicKeyBlockSize(SecKeyRef key) {
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;

    return ccn_write_uint_size(ccrsa_ctx_n(pubkey), ccrsa_ctx_m(pubkey));
}