34 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" \
35 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" \
36 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" \
37 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" \
38 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" \
42 "7FFFFFFFFFFFFFFFE487ED5110B4611A62633145C06E0E68" \
43 "948127044533E63A0105DF531D89CD9128A5043CC71A026E" \
44 "F7CA8CD9E69D218D98158536F92F8A1BA7F09AB6B6A8E122" \
45 "F242DABB312F3F637A262174D31BF6B585FFAE5B7A035BF6" \
46 "F71C35FDAD44CFD2D74F9208BE258FF324943328F67329C0" \
49 #if CONFIG_GMP || CONFIG_GCRYPT
53 bn = av_malloc(sizeof(*bn)); \
62 #define bn_set_word(bn, w) mpz_set_ui(bn, w)
63 #define bn_cmp(a, b) mpz_cmp(a, b)
64 #define bn_copy(to, from) mpz_set(to, from)
65 #define bn_sub_word(bn, w) mpz_sub_ui(bn, bn, w)
66 #define bn_cmp_1(bn) mpz_cmp_ui(bn, 1)
67 #define bn_num_bytes(bn) (mpz_sizeinbase(bn, 2) + 7) / 8
68 #define bn_bn2bin(bn, buf, len) \
70 memset(buf, 0, len); \
71 if (bn_num_bytes(bn) <= len) \
72 mpz_export(buf, NULL, 1, 1, 0, 0, bn); \
74 #define bn_bin2bn(bn, buf, len) \
78 mpz_import(bn, len, 1, 1, 0, 0, buf); \
80 #define bn_hex2bn(bn, buf, ret) \
84 ret = (mpz_set_str(bn, buf, 16) == 0); \
88 #define bn_modexp(bn, y, q, p) mpz_powm(bn, y, q, p)
89 #define bn_random(bn, num_bits) \
91 int bits = num_bits; \
93 for (bits = num_bits; bits > 0; bits -= 32) { \
94 mpz_mul_2exp(bn, bn, 32); \
95 mpz_add_ui(bn, bn, av_get_random_seed()); \
97 mpz_fdiv_r_2exp(bn, bn, num_bits); \
100 #define bn_new(bn) bn = gcry_mpi_new(1)
101 #define bn_free(bn) gcry_mpi_release(bn)
102 #define bn_set_word(bn, w) gcry_mpi_set_ui(bn, w)
103 #define bn_cmp(a, b) gcry_mpi_cmp(a, b)
104 #define bn_copy(to, from) gcry_mpi_set(to, from)
105 #define bn_sub_word(bn, w) gcry_mpi_sub_ui(bn, bn, w)
106 #define bn_cmp_1(bn) gcry_mpi_cmp_ui(bn, 1)
107 #define bn_num_bytes(bn) (gcry_mpi_get_nbits(bn) + 7) / 8
108 #define bn_bn2bin(bn, buf, len) gcry_mpi_print(GCRYMPI_FMT_USG, buf, len, NULL, bn)
109 #define bn_bin2bn(bn, buf, len) gcry_mpi_scan(&bn, GCRYMPI_FMT_USG, buf, len, NULL)
110 #define bn_hex2bn(bn, buf, ret) ret = (gcry_mpi_scan(&bn, GCRYMPI_FMT_HEX, buf, 0, 0) == 0)
111 #define bn_modexp(bn, y, q, p) gcry_mpi_powm(bn, y, q, p)
112 #define bn_random(bn, num_bits) gcry_mpi_randomize(bn, num_bits, GCRY_WEAK_RANDOM)
115 #define MAX_BYTES 18000
117 #define dh_new() av_malloc(sizeof(FF_DH))
119 static FFBigNum dh_generate_key(FF_DH *dh)
123 num_bytes = bn_num_bytes(dh->p) - 1;
124 if (num_bytes <= 0 || num_bytes > MAX_BYTES)
127 bn_new(dh->priv_key);
130 bn_random(dh->priv_key, 8 * num_bytes);
134 bn_free(dh->priv_key);
138 bn_modexp(dh->pub_key, dh->g, dh->priv_key, dh->p);
143 static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn,
144 uint32_t secret_key_len,
uint8_t *secret_key)
152 bn_modexp(k, pub_key_bn, dh->priv_key, dh->p);
153 bn_bn2bin(k, secret_key, secret_key_len);
157 return secret_key_len;
166 bn_free(dh->pub_key);
167 bn_free(dh->priv_key);
171 #define bn_new(bn) bn = BN_new()
172 #define bn_free(bn) BN_free(bn)
173 #define bn_set_word(bn, w) BN_set_word(bn, w)
174 #define bn_cmp(a, b) BN_cmp(a, b)
175 #define bn_copy(to, from) BN_copy(to, from)
176 #define bn_sub_word(bn, w) BN_sub_word(bn, w)
177 #define bn_cmp_1(bn) BN_cmp(bn, BN_value_one())
178 #define bn_num_bytes(bn) BN_num_bytes(bn)
179 #define bn_bn2bin(bn, buf, len) BN_bn2bin(bn, buf)
180 #define bn_bin2bn(bn, buf, len) bn = BN_bin2bn(buf, len, 0)
181 #define bn_hex2bn(bn, buf, ret) ret = BN_hex2bn(&bn, buf)
182 #define bn_modexp(bn, y, q, p) \
184 BN_CTX *ctx = BN_CTX_new(); \
186 return AVERROR(ENOMEM); \
187 if (!BN_mod_exp(bn, y, q, p, ctx)) { \
189 return AVERROR(EINVAL); \
194 #define dh_new() DH_new()
195 #define dh_generate_key(dh) DH_generate_key(dh)
197 static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn,
198 uint32_t secret_key_len,
uint8_t *secret_key)
200 if (secret_key_len < DH_size(dh))
202 return DH_compute_key(secret_key, pub_key_bn, dh);
240 bn_modexp(bn, y, q, p);
257 if (!(dh = dh_new()))
264 bn_hex2bn(dh->p,
P1024, ret);
268 bn_set_word(dh->g, 2);
269 dh->length = key_len;
286 if (!dh_generate_key(dh))
289 bn_hex2bn(q1,
Q1024, ret);
310 len = bn_num_bytes(dh->pub_key);
311 if (len <= 0 || len > pub_key_len)
315 memset(pub_key, 0, pub_key_len);
316 bn_bn2bin(dh->pub_key, pub_key + pub_key_len - len, len);
322 int pub_key_len,
uint8_t *secret_key,
329 bn_bin2bn(pub_key_bn, pub_key, pub_key_len);
334 bn_hex2bn(q1,
Q1024, ret);
343 }
else if ((ret = dh_compute_key(dh, pub_key_bn, secret_key_len,
357 static int test_random_shared_secret(
void)
361 uint8_t pubkey1[128], pubkey2[128];
362 uint8_t sharedkey1[128], sharedkey2[128];
366 if (!peer1 || !peer2) {
379 sharedkey1,
sizeof(sharedkey1))) < 0)
382 sharedkey2,
sizeof(sharedkey2))) < 0)
384 if (memcmp(sharedkey1, sharedkey2,
sizeof(sharedkey1))) {
385 printf(
"Mismatched generated shared key\n");
388 printf(
"Generated shared key ok\n");
396 static const char *private_key =
397 "976C18FCADC255B456564F74F3EEDA59D28AF6B744D743F2357BFD2404797EF896EF1A"
398 "7C1CBEAAA3AB60AF3192D189CFF3F991C9CBBFD78119FCA2181384B94011943B6D6F28"
399 "9E1B708E2D1A0C7771169293F03DA27E561F15F16F0AC9BC858C77A80FA98FD088A232"
400 "19D08BE6F165DE0B02034B18705829FAD0ACB26A5B75EF";
401 static const char *public_key =
402 "F272ECF8362257C5D2C3CC2229CF9C0A03225BC109B1DBC76A68C394F256ACA3EF5F64"
403 "FC270C26382BF315C19E97A76104A716FC998A651E8610A3AE6CF65D8FAE5D3F32EEA0"
404 "0B32CB9609B494116A825D7142D17B88E3D20EDD98743DE29CF37A23A9F6A58B960591"
405 "3157D5965FCB46DDA73A1F08DD897BAE88DFE6FC937CBA";
406 static const uint8_t public_key_bin[] = {
407 0xf2, 0x72, 0xec, 0xf8, 0x36, 0x22, 0x57, 0xc5, 0xd2, 0xc3, 0xcc, 0x22,
408 0x29, 0xcf, 0x9c, 0x0a, 0x03, 0x22, 0x5b, 0xc1, 0x09, 0xb1, 0xdb, 0xc7,
409 0x6a, 0x68, 0xc3, 0x94, 0xf2, 0x56, 0xac, 0xa3, 0xef, 0x5f, 0x64, 0xfc,
410 0x27, 0x0c, 0x26, 0x38, 0x2b, 0xf3, 0x15, 0xc1, 0x9e, 0x97, 0xa7, 0x61,
411 0x04, 0xa7, 0x16, 0xfc, 0x99, 0x8a, 0x65, 0x1e, 0x86, 0x10, 0xa3, 0xae,
412 0x6c, 0xf6, 0x5d, 0x8f, 0xae, 0x5d, 0x3f, 0x32, 0xee, 0xa0, 0x0b, 0x32,
413 0xcb, 0x96, 0x09, 0xb4, 0x94, 0x11, 0x6a, 0x82, 0x5d, 0x71, 0x42, 0xd1,
414 0x7b, 0x88, 0xe3, 0xd2, 0x0e, 0xdd, 0x98, 0x74, 0x3d, 0xe2, 0x9c, 0xf3,
415 0x7a, 0x23, 0xa9, 0xf6, 0xa5, 0x8b, 0x96, 0x05, 0x91, 0x31, 0x57, 0xd5,
416 0x96, 0x5f, 0xcb, 0x46, 0xdd, 0xa7, 0x3a, 0x1f, 0x08, 0xdd, 0x89, 0x7b,
417 0xae, 0x88, 0xdf, 0xe6, 0xfc, 0x93, 0x7c, 0xba
419 static const uint8_t peer_public_key[] = {
420 0x58, 0x66, 0x05, 0x49, 0x94, 0x23, 0x2b, 0x66, 0x52, 0x13, 0xff, 0x46,
421 0xf2, 0xb3, 0x79, 0xa9, 0xee, 0xae, 0x1a, 0x13, 0xf0, 0x71, 0x52, 0xfb,
422 0x93, 0x4e, 0xee, 0x97, 0x05, 0x73, 0x50, 0x7d, 0xaf, 0x02, 0x07, 0x72,
423 0xac, 0xdc, 0xa3, 0x95, 0x78, 0xee, 0x9a, 0x19, 0x71, 0x7e, 0x99, 0x9f,
424 0x2a, 0xd4, 0xb3, 0xe2, 0x0c, 0x1d, 0x1a, 0x78, 0x4c, 0xde, 0xf1, 0xad,
425 0xb4, 0x60, 0xa8, 0x51, 0xac, 0x71, 0xec, 0x86, 0x70, 0xa2, 0x63, 0x36,
426 0x92, 0x7c, 0xe3, 0x87, 0xee, 0xe4, 0xf1, 0x62, 0x24, 0x74, 0xb4, 0x04,
427 0xfa, 0x5c, 0xdf, 0xba, 0xfa, 0xa3, 0xc2, 0xbb, 0x62, 0x27, 0xd0, 0xf4,
428 0xe4, 0x43, 0xda, 0x8a, 0x88, 0x69, 0x60, 0xe2, 0xdb, 0x75, 0x2a, 0x98,
429 0x9d, 0xb5, 0x50, 0xe3, 0x99, 0xda, 0xe0, 0xa6, 0x14, 0xc9, 0x80, 0x12,
430 0xf9, 0x3c, 0xac, 0x06, 0x02, 0x7a, 0xde, 0x74
432 static const uint8_t shared_secret[] = {
433 0xb2, 0xeb, 0xcb, 0x71, 0xf3, 0x61, 0xfb, 0x5b, 0x4e, 0x5c, 0x4c, 0xcf,
434 0x5c, 0x08, 0x5f, 0x96, 0x26, 0x77, 0x1d, 0x31, 0xf1, 0xe1, 0xf7, 0x4b,
435 0x92, 0xac, 0x82, 0x2a, 0x88, 0xc7, 0x83, 0xe1, 0xc7, 0xf3, 0xd3, 0x1a,
436 0x7d, 0xc8, 0x31, 0xe3, 0x97, 0xe4, 0xec, 0x31, 0x0e, 0x8f, 0x73, 0x1a,
437 0xe4, 0xf6, 0xd8, 0xc8, 0x94, 0xff, 0xa0, 0x03, 0x84, 0x03, 0x0f, 0xa5,
438 0x30, 0x5d, 0x67, 0xe0, 0x7a, 0x3b, 0x5f, 0xed, 0x4c, 0xf5, 0xbc, 0x18,
439 0xea, 0xd4, 0x77, 0xa9, 0x07, 0xb3, 0x54, 0x0b, 0x02, 0xd9, 0xc6, 0xb8,
440 0x66, 0x5e, 0xec, 0xa4, 0xcd, 0x47, 0xed, 0xc9, 0x38, 0xc6, 0x91, 0x08,
441 0xf3, 0x85, 0x9b, 0x69, 0x16, 0x78, 0x0d, 0xb7, 0x74, 0x51, 0xaa, 0x5b,
442 0x4d, 0x74, 0xe4, 0x29, 0x2e, 0x9e, 0x8e, 0xf7, 0xe5, 0x42, 0x83, 0xb0,
443 0x65, 0xb0, 0xce, 0xc6, 0xb2, 0x8f, 0x5b, 0xb0
446 static int test_ref_data(
void)
456 bn_hex2bn(dh->priv_key, private_key, ret);
459 bn_hex2bn(dh->pub_key, public_key, ret);
464 if (memcmp(pubkey_test, public_key_bin,
sizeof(pubkey_test))) {
465 printf(
"Mismatched generated public key\n");
469 printf(
"Generated public key ok\n");
472 sharedkey_test,
sizeof(sharedkey_test))) < 0)
474 if (memcmp(shared_secret, sharedkey_test,
sizeof(sharedkey_test))) {
475 printf(
"Mismatched generated shared key\n");
478 printf(
"Generated shared key ok\n");
487 if (test_random_shared_secret() < 0)
489 if (test_ref_data() < 0)
uint32_t p[AV_BF_ROUNDS+2]
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
int ff_dh_write_public_key(FF_DH *dh, uint8_t *pub_key, int pub_key_len)
Write the public key into the given buffer.
static int dh_is_valid_public_key(FFBigNum y, FFBigNum p, FFBigNum q)
int ff_dh_compute_shared_secret_key(FF_DH *dh, const uint8_t *pub_key, int pub_key_len, uint8_t *secret_key, int secret_key_len)
Compute the shared secret key from the private FF_DH value and the other party's public value...
static const uint8_t q1[256]
int ff_dh_generate_public_key(FF_DH *dh)
Generate a public key.
void ff_dh_free(FF_DH *dh)
Free a Diffie-Hellmann context.
av_cold FF_DH * ff_dh_init(int key_len)
Initialize a Diffie-Hellmann context.
int main(int argc, char **argv)