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; }
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; }
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; }
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(¶mItem, 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; }
// // 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); }
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; }
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(¶mItem, 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; }
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); }
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); }
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; }