/* Private key static functions. */
static void SecECPrivateKeyDestroy(SecKeyRef key) {
    /* Zero out the public key */
    ccec_full_ctx_t fullkey;
    fullkey.hdr = key->key;
    if (ccec_ctx_cp(fullkey).zp)
        cc_zero(ccec_full_ctx_size(ccn_sizeof_n(ccec_ctx_n(fullkey))), fullkey.hdr);
}
static inline ccdh_full_ctx_t SecDH_priv(SecDHContext dh)
{
    void *p = dh;
    cczp_t zp = { .u = p };
    cc_size s = ccn_sizeof_n(cczp_n(zp));
    ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) };
    return priv;
}

static inline size_t SecDH_context_size(size_t p_len)
{
    cc_size n = ccn_nof_size(p_len);
    cc_size real_p_len = ccn_sizeof_n(n);
    size_t context_size = ccdh_gp_size(real_p_len)+ccdh_full_ctx_size(real_p_len);
    return context_size;
}
示例#3
0
/* Set DH parameters - Server only */
int
tls_handshake_set_dh_parameters(tls_handshake_t filter, tls_buffer *params)
{
    assert(filter->isServer);
    assert(params);
    const uint8_t *der, *der_end;
    size_t n;

    der = params->data;
    der_end = params->data + params->length;
    n = ccder_decode_dhparam_n(der, der_end);

    sslFree(filter->dhParams.gp);
    filter->dhParams.gp = sslMalloc(ccdh_gp_size(ccn_sizeof_n(n)));
    if(!filter->dhParams.gp) {
        return errSSLAllocate;
    }

    CCDH_GP_N(filter->dhParams) = n;

    der = ccder_decode_dhparams(filter->dhParams, der, der_end);
    if (der == NULL) {
        return errSSLParam;
    } else {
        return 0;
    }
}
/* Public key static functions. */
static void SecECPublicKeyDestroy(SecKeyRef key) {
    /* Zero out the public key */
    ccec_pub_ctx_t pubkey;
    pubkey.pub = key->key;
    if (ccec_ctx_cp(pubkey).zp)
        cc_zero(ccec_pub_ctx_size(ccn_sizeof_n(ccec_ctx_n(pubkey))), pubkey.pub);
}
示例#5
0
void SecDHDestroy(SecDHContext dh) {
	/* Zero out key material. */
    ccdh_gp_t gp = SecDH_gp(dh);
    cc_size p_len = ccn_sizeof_n(ccdh_gp_n(gp));
    size_t context_size = SecDH_context_size(p_len);

    bzero(dh, context_size);
    free(dh);
}
OSStatus SecDHCreateFromParameters(const uint8_t *params,
	size_t params_len, SecDHContext *pdh)
{
    DERReturn drtn;
	DERItem paramItem = {(DERByte *)params, params_len};
	DER_DHParams decodedParams;
    uint32_t l;

    drtn = DERParseSequence(&paramItem,
                            DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs,
                            &decodedParams, sizeof(decodedParams));
    if(drtn)
        return drtn;

    drtn = DERParseInteger(&decodedParams.l, &l);
    if(drtn)
        return drtn;
    cc_size n = ccn_nof_size(decodedParams.p.length);
    cc_size p_len = ccn_sizeof_n(n);
    size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len);
    void *context = malloc(context_size);
    if(context==NULL)
        return errSecAllocate;

    bzero(context, context_size);

    ccdh_gp_t gp;
    gp.gp = context;

    CCDH_GP_N(gp) = n;
    CCDH_GP_L(gp) = l;

    if(ccn_read_uint(n, CCDH_GP_PRIME(gp), decodedParams.p.length, decodedParams.p.data))
        goto errOut;
    if(decodedParams.recip.length) {
        if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), decodedParams.recip.length, decodedParams.recip.data))
            goto errOut;
        gp.zp.zp->mod_prime = cczp_mod;
    } else {
        cczp_init(gp.zp);
    };

    if(ccn_read_uint(n, CCDH_GP_G(gp), decodedParams.g.length, decodedParams.g.data))
        goto errOut;

    *pdh = (SecDHContext) context;
    return errSecSuccess;

errOut:
    SecDHDestroy(context);
    *pdh = NULL;
    return errSecInvalidKey;
}
static OSStatus SecECPublicKeyInit(SecKeyRef key,
    const uint8_t *keyData, CFIndex keyDataLength, SecKeyEncoding encoding) {
    ccec_pub_ctx_t pubkey;
    pubkey.pub = key->key;
    OSStatus err = errSecParam;

    switch (encoding) {
    case kSecDERKeyEncoding:
    {
        const SecDERKey *derKey = (const SecDERKey *)keyData;
        if (keyDataLength != sizeof(SecDERKey)) {
            err = errSecDecode;
            break;
        }

        ccec_const_cp_t cp = getCPForPublicSize(derKey->keyLength);

        /* TODO: Parse and use real params from passed in derKey->algId.params */
        err = (ccec_import_pub(cp, derKey->keyLength, derKey->key, pubkey)
               ? errSecDecode : errSecSuccess);
        break;
    }
    case kSecKeyEncodingBytes:
    {
        ccec_const_cp_t cp = getCPForPublicSize(keyDataLength);
        err = (ccec_import_pub(cp, keyDataLength, keyData, pubkey)
               ? errSecDecode : errSecSuccess);
        break;
    }
    case kSecExtractPublicFromPrivate:
    {
        ccec_full_ctx_t fullKey;
        fullKey._full = (ccec_full_ctx *) keyData;

        cc_size fullKeyN = ccec_ctx_n(fullKey);
        require(fullKeyN <= ccn_nof(kMaximumECKeySize), errOut);
        memcpy(pubkey._pub, fullKey.pub, ccec_pub_ctx_size(ccn_sizeof_n(fullKeyN)));
        err = errSecSuccess;
        break;
    }
    case kSecKeyEncodingApplePkcs1:
    default:
        err = errSecParam;
        break;
    }

errOut:
    return err;
}
示例#8
0
void ccz_lsl(ccz *r, const ccz *s, size_t k) {
    ccz_set_sign(r, ccz_sign(s));
    ccz_set_capacity(r, ccz_n(s) + ccn_nof(k));
    cc_size kn = k / CCN_UNIT_BITS;
    k &= (CCN_UNIT_BITS - 1);
    if (k) {
        r->u[kn + ccz_n(s)] = ccn_shift_left(ccz_n(s), r->u + kn, s->u, k);
        ccz_set_n(r, ccn_n(ccz_n(s) + kn + 1, r->u));
    } else if (kn || r != s) {
        /* Must copy in reverse due to potential overlap. */
        CC_MEMMOVE(r->u + kn, s->u, ccn_sizeof_n(ccz_n(s)));
        ccz_set_n(r, ccz_n(s) + kn);
    }
    ccn_zero(kn, r->u);
}
示例#9
0
int ccn_random_bits(cc_size nbits, cc_unit *r, struct ccrng_state *rng) {
    cc_size n = ccn_nof(nbits);
    
    int result = ccrng_generate(rng, ccn_sizeof_n(n), r);
	if (result)
	{
		return result;
	}
	cc_size lbits = nbits & (CCN_UNIT_BITS - 1);
    if (lbits) {
        cc_unit msuMask = (~CC_UNIT_C(0)) >> (CCN_UNIT_BITS - lbits);
        r[n - 1] &= msuMask;
    }
    return result;
}
示例#10
0
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;
}
示例#11
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;
}
static inline ccdh_full_ctx_t vmdh_priv(struct vmdh *dh)
{
    void *p = dh;
    cczp_t zp = { .u = p };
    cc_size s = ccn_sizeof_n(cczp_n(zp));
    ccdh_full_ctx_t priv = { .hdr = (struct ccdh_ctx_header *)(p+ccdh_gp_size(s)) };
    return priv;
}

static uint32_t param_g = 5;

static const uint8_t param_p[] = {
    0xED, 0x42, 0x06, 0xE1, 0xDD, 0x09, 0x93, 0xA6,
    0x81, 0xAE, 0x00, 0x0D, 0xBF, 0x84, 0x7F, 0x7D,
    0x87, 0x64, 0x6B, 0x77, 0x24, 0x03, 0xB8, 0xC0,
    0xDC, 0xBE, 0x5B, 0x9C, 0x8E, 0x71, 0x09, 0x24,
    0x53, 0x77, 0x7F, 0x5D, 0x1A, 0xAD, 0x92, 0xD8,
    0xFE, 0xCD, 0x5C, 0xB4, 0xCA, 0x09, 0x17, 0x11,
    0xF3, 0x82, 0x01, 0x39, 0x4A, 0x09, 0xBA, 0x29,
    0x95, 0x2B, 0xC4, 0xCC, 0x56, 0x21, 0x97, 0x13
};

static const uint8_t client_priv[] = {
    0x32, 0x34, 0x73, 0x16, 0x7d, 0x79, 0xde, 0x47,
    0x22, 0x93, 0xf5, 0x86, 0x47, 0xf6, 0x7f, 0x7a,
    0xb6, 0x30, 0x16, 0x5b, 0xbf, 0xe1, 0x36, 0x0b,
    0xb4, 0xd2, 0x84, 0x3e, 0x57, 0x5f, 0xcb, 0xc6,
    0x6a, 0xae, 0x5d, 0x59, 0x4b, 0x70, 0x53, 0x22,
    0xb0, 0x51, 0x89, 0x30, 0x74, 0xfc, 0x95, 0x51,
    0x9c, 0xc9, 0xf7, 0xac, 0x8c, 0x37, 0xfd, 0xc1,
    0x0e, 0x02, 0x6e, 0x69, 0x6c, 0xca, 0x2a, 0x95
};

static const uint8_t client_pub[] = {
    0x15, 0xDF, 0x17, 0x6E, 0xB4, 0x95, 0xA7, 0x92,
    0x41, 0xB6, 0xF1, 0x93, 0x19, 0xDB, 0x34, 0xF1,
    0xE0, 0x0D, 0x62, 0xCD, 0x55, 0xC7, 0x0B, 0x27,
    0xB7, 0x53, 0x1A, 0x28, 0x65, 0x11, 0xF0, 0xF6,
    0xA6, 0xE1, 0x5B, 0x86, 0x1D, 0x67, 0x85, 0x19,
    0x6D, 0xD6, 0x80, 0xFF, 0x5C, 0xEB, 0xC3, 0x2D,
    0xC3, 0xCB, 0xD2, 0xD4, 0x66, 0x93, 0xF4, 0xFC,
    0xF1, 0xF4, 0x8B, 0x61, 0x0F, 0x02, 0xF5, 0x19
};

static const uint8_t server_pub[] = {
    0x73, 0xC5, 0xF8, 0xF8, 0xB8, 0x9C, 0xB0, 0x5F,
    0xD6, 0xC6, 0x49, 0x5C, 0x70, 0xF5, 0x90, 0xB3,
    0x8A, 0xD3, 0xD0, 0x12, 0x99, 0x47, 0x60, 0xC2,
    0x5B, 0xF7, 0x18, 0x3A, 0x19, 0xF5, 0x01, 0xA3,
    0x67, 0xBF, 0x57, 0x28, 0x7E, 0x99, 0xA8, 0xDB,
    0x97, 0xA4, 0xAF, 0xF2, 0x68, 0x47, 0xAB, 0x48,
    0xE3, 0x4D, 0xF2, 0x94, 0xB4, 0xCC, 0xFC, 0x0C,
    0x50, 0xAD, 0xEF, 0x2E, 0x80, 0xA6, 0x20, 0x29
};

static const uint8_t pw[] = {
	0x31, 0x32, 0x33, 0x34
};

static const uint8_t pw_encr[] = {
    0x42, 0xd7, 0xa1, 0x08, 0x15, 0x8f, 0xdd, 0xc8,
    0xe8, 0x75, 0xea, 0xa2, 0xc2, 0x20, 0x28, 0xfa
};

#if 0
static void hexdump(const uint8_t *bytes, size_t len) {
	size_t ix;
	for (ix = 0; ix < len; ++ix) {
		printf("%02X", bytes[ix]);
	}
	printf("\n");
}
示例#13
0
size_t SecDHGetMaxKeyLength(SecDHContext dh) {
    cczp_const_t zp;
    zp.u = (cc_unit *)dh;

    return ccn_sizeof_n(cczp_n(zp));
}
示例#14
0
OSStatus SecDHCreateFromParameters(const uint8_t *params,
	size_t params_len, SecDHContext *pdh)
{
    // We support DomainParameters as specified in PKCS#3
    // (http://www.emc.com/emc-plus/rsa-labs/standards-initiatives/pkcs-3-diffie-hellman-key-agreement-standar.htm)
    // DHParameter ::= SEQUENCE {
    //   prime INTEGER, -- p
    //   base INTEGER, -- g
    //   privateValueLength INTEGER OPTIONAL }

    DERReturn drtn;
	DERItem paramItem = {(DERByte *)params, params_len};
	DER_DHParams decodedParams;
    uint32_t l = 0;

    drtn = DERParseSequence(&paramItem,
                            DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs,
                            &decodedParams, sizeof(decodedParams));
    if(drtn)
        return drtn;

    if (decodedParams.l.length > 0) {
        drtn = DERParseInteger(&decodedParams.l, &l);
        if(drtn)
            return drtn;
    }
    cc_size n = ccn_nof_size(decodedParams.p.length);
    cc_size p_len = ccn_sizeof_n(n);
    size_t context_size = ccdh_gp_size(p_len)+ccdh_full_ctx_size(p_len);
    void *context = malloc(context_size);
    if(context==NULL)
        return errSecAllocate;

    bzero(context, context_size);

    ccdh_gp_t gp;
    gp.gp = context;

    CCDH_GP_N(gp) = n;
    CCDH_GP_L(gp) = l;

    if(ccn_read_uint(n, CCDH_GP_PRIME(gp), decodedParams.p.length, decodedParams.p.data))
        goto errOut;
    if(decodedParams.recip.length) {
        if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), decodedParams.recip.length, decodedParams.recip.data))
            goto errOut;
        CCZP_MOD_PRIME(gp.zp) = cczp_mod;
    } else {
        cczp_init(gp.zp);
    };

    if(ccn_read_uint(n, CCDH_GP_G(gp), decodedParams.g.length, decodedParams.g.data))
        goto errOut;

    *pdh = (SecDHContext) context;
    return errSecSuccess;

errOut:
    SecDHDestroy(context);
    *pdh = NULL;
    return errSecInvalidKey;
}
示例#15
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;
}
示例#16
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;
}
示例#17
0
/* 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);
}
示例#18
0
int ccdh_test_compute_vector(const struct ccdh_compute_vector *v)
{
    int result,r1,r2;
    const cc_size n = ccn_nof(v->len);
    const size_t s = ccn_sizeof_n(n);
    unsigned char z[v->zLen];
    size_t zLen;
    unsigned char tmp[v->zLen]; // for negative testing
    uint32_t status=0;
    uint32_t nb_test=0;

    ccdh_gp_decl(s, gp);
    ccdh_full_ctx_decl(s, a);
    ccdh_full_ctx_decl(s, b);
    cc_unit p[n];
    cc_unit g[n];
    cc_unit r[n];
    cc_unit q[n];

    // Bail to errOut when unexpected error happens.
    // Try all usecases otherwise

    if((result=ccn_read_uint(n, p, v->pLen, v->p)))
        goto errOut;
    if((result=ccn_read_uint(n, g, v->gLen, v->g)))
        goto errOut;
    if((result=ccn_read_uint(n, q, v->qLen, v->q)))
        goto errOut;

    ccdh_init_gp_with_order(gp, n, p, g, q);

    ccdh_ctx_init(gp, a);
    ccdh_ctx_init(gp, b);

    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // private key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_y(a), v->yaLen, v->ya))) // public key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_x(b), v->xbLen, v->xb))) // private key
        goto errOut;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->ybLen, v->yb))) // public key
        goto errOut;

    /*
     * Main test
     */

    /* try one side */
    zLen = v->zLen;
    r1=ccdh_compute_key(a, b, r);
    ccn_write_uint_padded(n, r, zLen, z);
    r1|=memcmp(z, v->z, zLen);

    /* try the other side */
    zLen = v->zLen;
    r2=ccdh_compute_key(b, a, r);
    ccn_write_uint_padded(n, r, zLen, z);
    r2|=memcmp(z, v->z, zLen);

    if ((!(r1||r2) && v->valid)||((r1||r2) && !v->valid))
    {
        status|=1<<nb_test;
    }
    nb_test++;

    // We are done if the test is not valid
    if (!v->valid) goto doneOut;

    /*
     * Corner case / negative testing
     * Only applicable for valid tests
     */

    /* Output is 1 (use private key is (p-1)/2)*/
    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->pLen, v->p))) // private key
        goto errOut;
    ccn_sub1(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1);
    ccn_shift_right(n,ccdh_ctx_x(a),ccdh_ctx_x(a),1);
    if ((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    if((result=ccn_read_uint(n, ccdh_ctx_x(a), v->xaLen, v->xa))) // restore private key
        goto errOut;
    nb_test++;
    
    
    /* negative testing (1 < y < p-1)*/
    /* public y = 0 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = 1 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    tmp[zLen-1]=1;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
        goto errOut;

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p-1 */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
    {
        goto errOut;
    }
    ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1);

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* 
     * When the order is in defined in the group 
     *  check that the implementation check the order of the public value:
     *      public y = g+1 (for rfc5114 groups, g+1 is not of order q)
     */
    if (ccdh_gp_order_bitlen(gp))
    {
        if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->gLen, v->g)))
        {
            goto errOut;
        }
        ccn_add1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),1);

        if((result=ccdh_compute_key(a, b, r))!=0)
        {
            status|=1<<nb_test;
        }
        nb_test++;
    }


    /* positive testing at the boundaries of (1 < y < p-1)*/

    // Don't set the order in gp because 2 and p-2 are not of order q
    ccdh_init_gp(gp, n, p, g, 0);

    /* public y = 2 */
    zLen = v->zLen;
    cc_zero(sizeof(tmp),tmp);
    tmp[zLen-1]=2;
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), zLen, tmp)))
    {
        goto errOut;
    }
    if((result=ccdh_compute_key(a, b, r))==0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* public y = p-2 */
    if((result=ccn_read_uint(n, ccdh_ctx_y(b), v->pLen, v->p)))
    {
        goto errOut;
    }
    ccn_sub1(n,ccdh_ctx_y(b),ccdh_ctx_y(b),2);

    if((result=ccdh_compute_key(a, b, r))==0)
    {
        status|=1<<nb_test;
    }
    nb_test++;

    /* Negative testing: p is even */
    if((result=ccn_read_uint(n, p, v->pLen, v->p)))
        goto errOut;
    ccn_set_bit(p,0,0); // Set LS bit to 0
    ccdh_init_gp(gp, n, p, g, 0);
    ccdh_ctx_init(gp, a);
    ccdh_ctx_init(gp, b);

    if((result=ccdh_compute_key(a, b, r))!=0)
    {
        status|=1<<nb_test;
    }
    nb_test++;


    /* Test aftermath */
doneOut:
    if ((nb_test==0) || (status!=((1<<nb_test)-1)))
    {
        result=1;
    }
    else
    {
        result=0; // Test is successful, Yeah!
    }

errOut:
    return result;
}
示例#19
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;
}
示例#20
0
/* Public key static functions. */
static void SecRSAPublicKeyDestroy(SecKeyRef key) {
    /* Zero out the public key */
    ccrsa_pub_ctx_t pubkey;
    pubkey.pub = key->key;
    cc_zero(ccrsa_pub_ctx_size(ccn_sizeof_n(ccrsa_ctx_n(pubkey))), pubkey.pub);
}
示例#21
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;
}
示例#22
0
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;		
}