int evrb_crypto_keys_compute(void* local_ctx, void* distant_ctx, int caller) { srtp_policy_t* loc_policy; srtp_policy_t* dist_policy; EVRB_CRYPTO* loc = (EVRB_CRYPTO*)local_ctx; EVRB_CRYPTO* dist = (EVRB_CRYPTO*)distant_ctx; unsigned char *master_key; int master_key_len; if(!local_ctx || !distant_ctx) return -1; loc_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t)); dist_policy = (srtp_policy_t*)malloc(sizeof(srtp_policy_t)); if(!loc_policy || !dist_policy) return -1; memcpy(loc_policy, &default_policy, sizeof(srtp_policy_t)); memcpy(dist_policy, &default_policy, sizeof(srtp_policy_t)); loc_policy->ssrc.type = ssrc_any_outbound; dist_policy->ssrc.type = ssrc_any_inbound; if (loc->dh == NULL) return -1; master_key = dh_compute_key(loc->dh, dist->key, &master_key_len); #ifndef NDEBUG { int i; printf("key1=%s\nkey2=%s\n", loc->key, dist->key); printf("master_key(%d)=", master_key_len); for (i = 0; i < master_key_len; i++) printf("%02x", master_key[i]); printf("\n"); } #endif loc_policy->key = (uint8_t*)malloc(EVRB_KEY_SIZE); dist_policy->key = (uint8_t*)malloc(EVRB_KEY_SIZE); // TODO: better key derivation /* Simmetric keys */ if (caller) { memcpy(loc_policy->key, master_key, EVRB_KEY_SIZE); memcpy(dist_policy->key, master_key+EVRB_KEY_SIZE, EVRB_KEY_SIZE); } else { memcpy(loc_policy->key, master_key+EVRB_KEY_SIZE, EVRB_KEY_SIZE); memcpy(dist_policy->key, master_key, EVRB_KEY_SIZE); } if(srtp_create(&loc->srtp_session, loc_policy)) return -1; if(srtp_create(&dist->srtp_session, dist_policy)) return -1; return 0; }
int dh_gm_compute_key(PACE_CTX * ctx, const BUF_MEM * s, const BUF_MEM * in, BN_CTX *bn_ctx) { int ret = 0; BUF_MEM * mem_h = NULL; BIGNUM * bn_s = NULL, *bn_h = NULL, *bn_g = NULL; DH *static_key = NULL, *ephemeral_key = NULL; check(ctx && ctx->static_key && s && ctx->ka_ctx, "Invalid arguments"); BN_CTX_start(bn_ctx); static_key = EVP_PKEY_get1_DH(ctx->static_key); if (!static_key) goto err; /* Convert nonce to BIGNUM */ bn_s = BN_bin2bn((unsigned char *) s->data, s->length, bn_s); if (!bn_s) goto err; /* complete the DH and convert the result to a BIGNUM */ mem_h = dh_compute_key(ctx->static_key, in, bn_ctx); if (!mem_h) goto err; bn_h = BN_bin2bn((unsigned char *) mem_h->data, mem_h->length, bn_h); if (!bn_h) goto err; /* Initialize ephemeral parameters with parameters from the static key */ ephemeral_key = DHparams_dup_with_q(static_key); if (!ephemeral_key) goto err; /* map to new generator */ bn_g = BN_CTX_get(bn_ctx); if (!bn_g || /* bn_g = g^s mod p */ !BN_mod_exp(bn_g, static_key->g, bn_s, static_key->p, bn_ctx) || /* ephemeral_key->g = bn_g * h mod p = g^s * h mod p */ !BN_mod_mul(ephemeral_key->g, bn_g, bn_h, static_key->p, bn_ctx)) goto err; /* Copy ephemeral key to context structure */ if (!EVP_PKEY_set1_DH(ctx->ka_ctx->key, ephemeral_key)) goto err; ret = 1; err: if (mem_h) { OPENSSL_cleanse(mem_h->data, mem_h->max); BUF_MEM_free(mem_h); } if (bn_h) BN_clear_free(bn_h); if (bn_s) BN_clear_free(bn_s); /* Decrement reference count, keys are still available via PACE_CTX */ if (static_key) DH_free(static_key); if (ephemeral_key) DH_free(ephemeral_key); BN_CTX_end(bn_ctx); return ret; }