/* 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;
}
Beispiel #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;
}
Beispiel #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;
}
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;
}
Beispiel #6
0
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;
}
Beispiel #7
0
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;
}