Beispiel #1
0
static inline int cczp_read_uint(cczp_t r, size_t data_size, const uint8_t *data)
{
    if(ccn_read_uint(ccn_nof_size(data_size), CCZP_PRIME(r), data_size, data) != 0) return -1;
    CCZP_N(r) = ccn_nof_size(data_size);
    cczp_init(r);
    return 0;
}
Beispiel #2
0
CCCryptorStatus
CCRSACryptorCreateFromData( CCRSAKeyType keyType, uint8_t *modulus, size_t modulusLength, 
                            uint8_t *exponent, size_t exponentLength,
                            uint8_t *p, size_t pLength, uint8_t *q, size_t qLength,
                            CCRSACryptorRef *ref)
{
    CCCryptorStatus retval = kCCSuccess;
	CCRSACryptor *rsaKey = NULL;
    size_t n = ccn_nof_size(modulusLength);
    cc_unit m[n];
    
    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
    __Require_Action(ccn_read_uint(n, m, modulusLength, modulus) == 0, errOut, retval = kCCParamError);
    size_t nbits = ccn_bitlen(n, m);

    __Require_Action((rsaKey = ccMallocRSACryptor(nbits, keyType)) != NULL, errOut, retval = kCCMemoryFailure);

    __Require_Action(ccn_read_uint(n, ccrsa_ctx_m(rsaKey->fk), modulusLength, modulus) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(n, ccrsa_ctx_e(rsaKey->fk), exponentLength, exponent) == 0, errOut, retval = kCCParamError);
    cczp_init(ccrsa_ctx_zm(rsaKey->fk));
    rsaKey->keySize = ccn_bitlen(n, ccrsa_ctx_m(rsaKey->fk));

	switch(keyType) {
		case ccRSAKeyPublic:
            rsaKey->keyType = ccRSAKeyPublic;
            break;
		
		case ccRSAKeyPrivate: {
            ccrsa_priv_ctx_t privk = ccrsa_ctx_private(rsaKey->fk);
            size_t psize = ccn_nof_size(pLength);
            size_t qsize = ccn_nof_size(qLength);

            
            CCZP_N(ccrsa_ctx_private_zp(privk)) = psize;
            __Require_Action(ccn_read_uint(psize, CCZP_PRIME(ccrsa_ctx_private_zp(privk)), pLength, p) == 0, errOut, retval = kCCParamError);
            CCZP_N(ccrsa_ctx_private_zq(privk)) = qsize;
            __Require_Action(ccn_read_uint(qsize, CCZP_PRIME(ccrsa_ctx_private_zq(privk)), qLength, q) == 0, errOut, retval = kCCParamError);

            ccrsa_crt_makekey(ccrsa_ctx_zm(rsaKey->fk), ccrsa_ctx_e(rsaKey->fk), ccrsa_ctx_d(rsaKey->fk),
                              ccrsa_ctx_private_zp(privk),
                              ccrsa_ctx_private_dp(privk), ccrsa_ctx_private_qinv(privk),
                              ccrsa_ctx_private_zq(privk), ccrsa_ctx_private_dq(privk));
            
            rsaKey->keyType = ccRSAKeyPrivate;

       		break;
        }
		
		default:
            retval = kCCParamError;
			goto errOut;
	}
	*ref = rsaKey;
	return kCCSuccess;
	
errOut:
	if(rsaKey) ccRSACryptorClear(rsaKey);
	return retval;
}
Beispiel #3
0
OSStatus SecDHCreate(uint32_t g, const uint8_t *p, size_t p_len,
	uint32_t l, const uint8_t *recip, size_t recip_len, SecDHContext *pdh)
{
    cc_size n = ccn_nof_size(p_len);
    size_t context_size = SecDH_context_size(p_len);
    void *context = malloc(context_size);
    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), p_len, p))
        goto errOut;
    if(recip) {
        if(ccn_read_uint(n+1, CCDH_GP_RECIP(gp), recip_len, recip))
            goto errOut;
        CCZP_MOD_PRIME(gp.zp) = cczp_mod;
    } else {
        cczp_init(gp.zp);
    };
    ccn_seti(n, CCDH_GP_G(gp), g);

    *pdh = (SecDHContext) context;

    return errSecSuccess;

errOut:
    SecDHDestroy(context);
    *pdh = NULL;
    return errSecInternal;

}
Beispiel #4
0
int ccz_cmpi(const ccz *s, uint32_t v)
{
    const size_t n = ccn_nof_size(sizeof(v));
    cc_unit td[n] = { ccn32_v(v) };
    struct ccz tt = { .u = td, .n = ccn_n(n, td), .sac = n, .isa = NULL };
    return ccz_cmp(s, &tt);
}
uint8_t *
ccder_encode_implicit_uint64(ccder_tag implicit_tag,
                                      uint64_t value,
                                      const uint8_t *der, uint8_t *der_end) {
    const cc_size n = ccn_nof_size(sizeof(value));
    cc_unit s[n] = { ccn64_v(value) };
    return ccder_encode_implicit_integer(implicit_tag, n, s, der, der_end);
}
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 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;
}
Beispiel #8
0
//
// 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);
}
Beispiel #9
0
int p12_pbe_gen(CFStringRef passphrase, uint8_t *salt_ptr, size_t salt_length, 
    unsigned iter_count, P12_PBE_ID pbe_id, uint8_t *data, size_t length)
{
    unsigned int hash_blocksize = CC_SHA1_BLOCK_BYTES;
    unsigned int hash_outputsize = CC_SHA1_DIGEST_LENGTH;

    if (!passphrase)
        return -1;

    /* generate diversifier block */
    unsigned char diversifier[hash_blocksize];    
    memset(diversifier, pbe_id, sizeof(diversifier));

    /* convert passphrase to BE UTF16 and append double null */
    CFDataRef passphrase_be_unicode = CFStringCreateExternalRepresentation(kCFAllocatorDefault, passphrase, kCFStringEncodingUTF16BE, '\0');
    if (!passphrase_be_unicode)
        return -1;
    uint8_t null_termination[2] = { 0, 0 };
    CFMutableDataRef passphrase_be_unicode_null_term = CFDataCreateMutableCopy(NULL, 0, passphrase_be_unicode);
    CFRelease(passphrase_be_unicode);
    if (!passphrase_be_unicode_null_term)
        return -1;
    CFDataAppendBytes(passphrase_be_unicode_null_term, null_termination, sizeof(null_termination));

    /* generate passphrase block */
    uint8_t *passphrase_data = NULL;
    size_t passphrase_data_len = 0;
    size_t passphrase_length = CFDataGetLength(passphrase_be_unicode_null_term);
    const unsigned char *passphrase_ptr = CFDataGetBytePtr(passphrase_be_unicode_null_term);
    passphrase_data = concatenate_to_blocksize(passphrase_ptr, passphrase_length, hash_blocksize, &passphrase_data_len);
    CFRelease(passphrase_be_unicode_null_term);
    if (!passphrase_data)
        return -1;

    /* generate salt block */
    uint8_t *salt_data = NULL;
    size_t salt_data_len = 0;
    if (salt_length)
        salt_data = concatenate_to_blocksize(salt_ptr, salt_length, hash_blocksize, &salt_data_len);
    if (!salt_data)
        return -1;
    
    /* generate S||P block */
    size_t I_length = salt_data_len + passphrase_data_len;
    uint8_t *I_data = malloc(I_length);
    if (!I_data)
        return -1;
        
    memcpy(I_data + 0, salt_data, salt_data_len);
    memcpy(I_data + salt_data_len, passphrase_data, passphrase_data_len);
    free(salt_data);
    free(passphrase_data);

    /* round up output buffer to multiple of hash block size and allocate */
    size_t hash_output_blocks = (length + hash_outputsize - 1) / hash_outputsize;
    size_t temp_buf_size = hash_output_blocks * hash_outputsize;
    uint8_t *temp_buf = malloc(temp_buf_size);
    uint8_t *cursor = temp_buf;
    if (!temp_buf)
        return -1;

    /* 64 bits cast(s): worst case here is we dont hash all the data and incorectly derive the wrong key,
       when the passphrase + salt are over 2^32 bytes long */
    /* loop over output in hash_output_size increments */
    while (cursor < temp_buf + temp_buf_size) {
        CC_SHA1_CTX ctx;
        CC_SHA1_Init(&ctx);
        CC_SHA1_Update(&ctx, diversifier, (CC_LONG)sizeof(diversifier));
        assert(I_length<=UINT32_MAX); /* debug check. Correct as long as CC_LONG is uint32_t */
        CC_SHA1_Update(&ctx, I_data, (CC_LONG)I_length);
        CC_SHA1_Final(cursor, &ctx);

        /* run block through SHA-1 for iteration count */
        unsigned int i;
        for (i = 1; /*first round done above*/ i < iter_count; i++)
            CC_SHA1(cursor, hash_outputsize, cursor);

        /*
         * b) Concatenate copies of A[i] to create a string B of 
         *    length v bits (the final copy of A[i]i may be truncated 
         *    to create B).
         */
        size_t A_i_len = 0;
        uint8_t *A_i = concatenate_to_blocksize(cursor, 
            hash_outputsize, hash_blocksize, &A_i_len);
        if (!A_i)
            return -1;
        
        /*
         * c) Treating I as a concatenation I[0], I[1], ..., 
         *    I[k-1] of v-bit blocks, where k = ceil(s/v) + ceil(p/v),
         *    modify I by setting I[j]=(I[j]+B+1) mod (2 ** v)
         *    for each j.
         */

        /* tmp1 = B+1 */

        const cc_size tmp_n = ccn_nof_size(A_i_len + 1) > ccn_nof_size(hash_blocksize) ? ccn_nof_size(A_i_len + 1) : ccn_nof_size(hash_blocksize);
        cc_unit tmp1[tmp_n];
        ccn_read_uint(tmp_n, tmp1, A_i_len, A_i);
        ccn_add1(tmp_n, tmp1, tmp1, 1);

        free(A_i);

        cc_unit tmp2[tmp_n];
        unsigned int j;
        for (j = 0; j < I_length; j+=hash_blocksize) {
            /* tempg = I[j];  */
            ccn_read_uint(tmp_n, tmp2, hash_blocksize, I_data + j);
            /* tempg += tmp1 */
            ccn_add(tmp_n, tmp2, tmp2, tmp1);
            
            /* I[j] = tempg mod 2**v
               Just clear all the high bits above 2**v
               In practice at most it rolled over by 1 bit, since all we did was add so
               we should only clear one bit at most.
             */
            size_t bitSize;
            const size_t hash_blocksize_bits = hash_blocksize * 8;
            while ((bitSize = ccn_bitlen(tmp_n, tmp2)) > hash_blocksize_bits)
            {
                ccn_set_bit(tmp2, bitSize - 1, 0);
            }

            ccn_write_uint_padded(tmp_n, tmp2, hash_blocksize, I_data + j);
        }

        cursor += hash_outputsize;
    }

    /*
     * 7. Concatenate A[1], A[2], ..., A[c] together to form a 
     *    pseudo-random bit string, A.
     *
     * 8. Use the first n bits of A as the output of this entire 
     *    process.
     */
    memmove(data, temp_buf, length);
    free(temp_buf);
    free(I_data);
    return 0;
}
Beispiel #10
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;
}
Beispiel #11
0
void ccz_addi(ccz *r, const ccz *s, uint32_t v) {
    const size_t n = ccn_nof_size(sizeof(v));
    cc_unit td[n] = { ccn32_v(v) };
    struct ccz ts = { .u = td, .n = ccn_n(n, td), .sac = n, .isa = NULL };
    ccz_add(r, s, &ts);
}
Beispiel #12
0
CCCryptorStatus 
CCRSACryptorCreatePairFromData(uint32_t e, 
    uint8_t *xp1, size_t xp1Length,
    uint8_t *xp2, size_t xp2Length,
    uint8_t *xp, size_t xpLength,
    uint8_t *xq1, size_t xq1Length,
    uint8_t *xq2, size_t xq2Length,
    uint8_t *xq, size_t xqLength,
    CCRSACryptorRef *publicKey, CCRSACryptorRef *privateKey,
    uint8_t *retp, size_t *retpLength,
    uint8_t *retq, size_t *retqLength,
    uint8_t *retm, size_t *retmLength,
    uint8_t *retd, size_t *retdLength)
{
    CCCryptorStatus retval;
    CCRSACryptor *privateCryptor = NULL;
    CCRSACryptor *publicCryptor = NULL;
    cc_unit x_p1[ccn_nof_size(xp1Length)];
    cc_unit x_p2[ccn_nof_size(xp2Length)];
    cc_unit x_p[ccn_nof_size(xpLength)];
    cc_unit x_q1[ccn_nof_size(xq1Length)];
    cc_unit x_q2[ccn_nof_size(xq2Length)];
    cc_unit x_q[ccn_nof_size(xqLength)];
    cc_unit e_value[1];
    size_t nbits = xpLength * 8 + xqLength * 8; // or we'll add this as a parameter.  This appears to be correct for FIPS
    cc_size n = ccn_nof(nbits);
    cc_unit p[n], q[n], m[n], d[n];
    cc_size np, nq, nm, nd;
    
    np = nq = nm = nd = n;
    
    CC_DEBUG_LOG(ASL_LEVEL_ERR, "Entering\n");
    e_value[0] = (cc_unit) e;

    __Require_Action((privateCryptor = ccMallocRSACryptor(nbits, ccRSAKeyPrivate)) != NULL, errOut, retval = kCCMemoryFailure);

    __Require_Action(ccn_read_uint(ccn_nof_size(xp1Length), x_p1, xp1Length, xp1) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(ccn_nof_size(xp2Length), x_p2, xp2Length, xp2)== 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(ccn_nof_size(xpLength), x_p, xpLength, xp) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(ccn_nof_size(xq1Length), x_q1, xq1Length, xq1) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(ccn_nof_size(xq2Length), x_q2, xq2Length, xq2) == 0, errOut, retval = kCCParamError);
    __Require_Action(ccn_read_uint(ccn_nof_size(xqLength), x_q, xqLength, xq) == 0, errOut, retval = kCCParamError);
    
	__Require_Action(ccrsa_make_931_key(nbits, 1, e_value, 
                                        ccn_nof_size(xp1Length), x_p1, ccn_nof_size(xp2Length), x_p2, ccn_nof_size(xpLength), x_p,
                                        ccn_nof_size(xq1Length), x_q1, ccn_nof_size(xq2Length), x_q2, ccn_nof_size(xqLength), x_q,
                                        privateCryptor->fk,
                                        &np, p,
                                        &nq, q,
                                        &nm, m,
                                        &nd, d) == 0, errOut, retval = kCCDecodeError);
    
    privateCryptor->keyType = ccRSAKeyPrivate;
    
    __Require_Action((publicCryptor = CCRSACryptorGetPublicKeyFromPrivateKey(privateCryptor)) != NULL, errOut, retval = kCCMemoryFailure);

    *publicKey = publicCryptor;
    *privateKey = privateCryptor;
    ccn_write_arg(np, p, retp, retpLength);
    ccn_write_arg(nq, q, retq, retqLength);
    ccn_write_arg(nm, m, retm, retmLength);
    ccn_write_arg(nd, d, retd, retdLength);
    
    return kCCSuccess;
    
errOut:
    if(privateCryptor) ccRSACryptorClear(privateCryptor);
    if(publicCryptor) ccRSACryptorClear(publicCryptor);
    // CLEAR the bits
    *publicKey = *privateKey = NULL;
    return retval;

}
size_t
ccder_sizeof_implicit_uint64(ccder_tag implicit_tag, uint64_t value) {
    const cc_size n = ccn_nof_size(sizeof(value));
    cc_unit s[n] = { ccn64_v(value) };
    return ccder_sizeof_implicit_integer(implicit_tag, n, s);
}
Beispiel #14
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;		
}