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;
}
示例#2
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;
}
示例#3
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;
}
示例#4
0
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;
}
示例#5
0
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;
}
示例#6
0
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;
}