/* Compute an DH shared secret between private_key and public_key. Return the result in computed_key and the length of the result in bytes in *computed_key_len. Return 0 iff successful. */ int ccdh_compute_key(ccdh_full_ctx_t private_key, ccdh_pub_ctx_t public_key, cc_unit *r) { int result = CCDH_ERROR_DEFAULT; ccdh_const_gp_t gp = ccdh_ctx_gp(private_key); cc_size n=ccdh_gp_n(gp); /* Validated the public key */ result = ccdh_check_pub(gp,public_key); if(result!=0) { goto errOut; } /* Actual compuation */ cczp_power(gp.zp, r, ccdh_ctx_y(public_key), ccdh_ctx_x(private_key)); /* Result can't be 0 (computation issue) or 1 (y in the group) */ result = CCDH_INVALID_INPUT; if (!(ccn_is_zero_or_one(n,r))) { result = 0; } errOut: return result; }
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 SecDHGenerateKeypair(SecDHContext dh, uint8_t *pub_key, size_t *pub_key_len) { int result; ccdh_gp_t gp = SecDH_gp(dh); ccdh_full_ctx_t priv = SecDH_priv(dh); if((result = ccdh_generate_key(gp, &dhrng, priv))) return result; /* output y as a big endian byte buffer */ size_t ylen = ccn_write_uint_size(ccdh_gp_n(gp), ccdh_ctx_y(priv)); if(*pub_key_len < ylen) return errSecBufferTooSmall; ccn_write_uint(ccdh_gp_n(gp),ccdh_ctx_y(priv), ylen, pub_key); *pub_key_len = ylen; return errSecSuccess; }
int ccdh_import_priv(ccdh_const_gp_t gp, size_t in_len, const uint8_t *in, ccdh_full_ctx_t key) { const cc_unit *g = ccdh_gp_g(gp); ccdh_ctx_init(gp, key); cc_unit *x = ccdh_ctx_x(key); cc_unit *y = ccdh_ctx_y(key); if ((ccn_read_uint(ccdh_gp_n(gp), x, in_len, in))) return CCDH_INVALID_INPUT; if (ccn_cmp(ccdh_gp_n(gp), x, cczp_prime(gp.zp)) >= 0) return CCDH_SAFETY_CHECK; /* Generate the public key: y=g^x mod p */ cczp_power(gp.zp, y, g, x); return 0; }
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; }