OSStatus SecDHComputeKey(SecDHContext dh, const uint8_t *pub_key, size_t pub_key_len, uint8_t *computed_key, size_t *computed_key_len) { ccdh_gp_t gp = SecDH_gp(dh); ccdh_full_ctx_t priv = SecDH_priv(dh); ccdh_pub_ctx_decl_gp(gp, pub); cc_size n = ccdh_gp_n(gp); cc_unit r[n]; if(ccdh_import_pub(gp, pub_key_len, pub_key, pub)) return errSecInvalidKey; if(ccdh_compute_key(priv, pub, r)) return errSecInvalidKey; ccn_write_uint(n, r, *computed_key_len, computed_key); size_t out_size = ccn_write_uint_size(n, r); if(out_size < *computed_key_len) *computed_key_len=out_size; return errSecSuccess; }
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; }