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); \
102 if (!gcry_control(GCRYCTL_INITIALIZATION_FINISHED_P)) { \
103 if (!gcry_check_version("1.5.4")) \
104 return AVERROR(EINVAL); \
105 gcry_control(GCRYCTL_DISABLE_SECMEM, 0); \
106 gcry_control(GCRYCTL_INITIALIZATION_FINISHED, 0); \
108 bn = gcry_mpi_new(1); \
110 #define bn_free(bn) gcry_mpi_release(bn)
111 #define bn_set_word(bn, w) gcry_mpi_set_ui(bn, w)
112 #define bn_cmp(a, b) gcry_mpi_cmp(a, b)
113 #define bn_copy(to, from) gcry_mpi_set(to, from)
114 #define bn_sub_word(bn, w) gcry_mpi_sub_ui(bn, bn, w)
115 #define bn_cmp_1(bn) gcry_mpi_cmp_ui(bn, 1)
116 #define bn_num_bytes(bn) (gcry_mpi_get_nbits(bn) + 7) / 8
117 #define bn_bn2bin(bn, buf, len) gcry_mpi_print(GCRYMPI_FMT_USG, buf, len, NULL, bn)
118 #define bn_bin2bn(bn, buf, len) gcry_mpi_scan(&bn, GCRYMPI_FMT_USG, buf, len, NULL)
119 #define bn_hex2bn(bn, buf, ret) ret = (gcry_mpi_scan(&bn, GCRYMPI_FMT_HEX, buf, 0, 0) == 0)
120 #define bn_modexp(bn, y, q, p) gcry_mpi_powm(bn, y, q, p)
121 #define bn_random(bn, num_bits) gcry_mpi_randomize(bn, num_bits, GCRY_WEAK_RANDOM)
124 #define MAX_BYTES 18000
126 #define dh_new() av_malloc(sizeof(FF_DH))
128 static FFBigNum dh_generate_key(FF_DH *dh)
132 num_bytes = bn_num_bytes(dh->p) - 1;
133 if (num_bytes <= 0 || num_bytes > MAX_BYTES)
136 bn_new(dh->priv_key);
139 bn_random(dh->priv_key, 8 * num_bytes);
143 bn_free(dh->priv_key);
147 bn_modexp(dh->pub_key, dh->g, dh->priv_key, dh->p);
152 static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn,
153 uint32_t secret_key_len,
uint8_t *secret_key)
161 bn_modexp(k, pub_key_bn, dh->priv_key, dh->p);
162 bn_bn2bin(k, secret_key, secret_key_len);
166 return secret_key_len;
175 bn_free(dh->pub_key);
176 bn_free(dh->priv_key);
180 #define bn_new(bn) bn = BN_new()
181 #define bn_free(bn) BN_free(bn)
182 #define bn_set_word(bn, w) BN_set_word(bn, w)
183 #define bn_cmp(a, b) BN_cmp(a, b)
184 #define bn_copy(to, from) BN_copy(to, from)
185 #define bn_sub_word(bn, w) BN_sub_word(bn, w)
186 #define bn_cmp_1(bn) BN_cmp(bn, BN_value_one())
187 #define bn_num_bytes(bn) BN_num_bytes(bn)
188 #define bn_bn2bin(bn, buf, len) BN_bn2bin(bn, buf)
189 #define bn_bin2bn(bn, buf, len) bn = BN_bin2bn(buf, len, 0)
190 #define bn_hex2bn(bn, buf, ret) ret = BN_hex2bn(&bn, buf)
191 #define bn_modexp(bn, y, q, p) \
193 BN_CTX *ctx = BN_CTX_new(); \
195 return AVERROR(ENOMEM); \
196 if (!BN_mod_exp(bn, y, q, p, ctx)) { \
198 return AVERROR(EINVAL); \
203 #define dh_new() DH_new()
204 #define dh_generate_key(dh) DH_generate_key(dh)
206 static int dh_compute_key(FF_DH *dh, FFBigNum pub_key_bn,
207 uint32_t secret_key_len,
uint8_t *secret_key)
209 if (secret_key_len < DH_size(dh))
211 return DH_compute_key(secret_key, pub_key_bn, dh);
249 bn_modexp(bn, y, q, p);
266 if (!(dh = dh_new()))
273 bn_hex2bn(dh->p,
P1024, ret);
277 bn_set_word(dh->g, 2);
278 dh->length = key_len;
295 if (!dh_generate_key(dh))
298 bn_hex2bn(q1,
Q1024, ret);
319 len = bn_num_bytes(dh->pub_key);
320 if (len <= 0 || len > pub_key_len)
324 memset(pub_key, 0, pub_key_len);
325 bn_bn2bin(dh->pub_key, pub_key + pub_key_len - len, len);
331 int pub_key_len,
uint8_t *secret_key,
338 bn_bin2bn(pub_key_bn, pub_key, pub_key_len);
343 bn_hex2bn(q1,
Q1024, ret);
352 }
else if ((ret = dh_compute_key(dh, pub_key_bn, secret_key_len,
366 static int test_random_shared_secret(
void)
370 uint8_t pubkey1[128], pubkey2[128];
371 uint8_t sharedkey1[128], sharedkey2[128];
375 if (!peer1 || !peer2) {
388 sharedkey1,
sizeof(sharedkey1))) < 0)
391 sharedkey2,
sizeof(sharedkey2))) < 0)
393 if (memcmp(sharedkey1, sharedkey2,
sizeof(sharedkey1))) {
394 printf(
"Mismatched generated shared key\n");
397 printf(
"Generated shared key ok\n");
405 static const char *private_key =
406 "976C18FCADC255B456564F74F3EEDA59D28AF6B744D743F2357BFD2404797EF896EF1A"
407 "7C1CBEAAA3AB60AF3192D189CFF3F991C9CBBFD78119FCA2181384B94011943B6D6F28"
408 "9E1B708E2D1A0C7771169293F03DA27E561F15F16F0AC9BC858C77A80FA98FD088A232"
409 "19D08BE6F165DE0B02034B18705829FAD0ACB26A5B75EF";
410 static const char *public_key =
411 "F272ECF8362257C5D2C3CC2229CF9C0A03225BC109B1DBC76A68C394F256ACA3EF5F64"
412 "FC270C26382BF315C19E97A76104A716FC998A651E8610A3AE6CF65D8FAE5D3F32EEA0"
413 "0B32CB9609B494116A825D7142D17B88E3D20EDD98743DE29CF37A23A9F6A58B960591"
414 "3157D5965FCB46DDA73A1F08DD897BAE88DFE6FC937CBA";
415 static const uint8_t public_key_bin[] = {
416 0xf2, 0x72, 0xec, 0xf8, 0x36, 0x22, 0x57, 0xc5, 0xd2, 0xc3, 0xcc, 0x22,
417 0x29, 0xcf, 0x9c, 0x0a, 0x03, 0x22, 0x5b, 0xc1, 0x09, 0xb1, 0xdb, 0xc7,
418 0x6a, 0x68, 0xc3, 0x94, 0xf2, 0x56, 0xac, 0xa3, 0xef, 0x5f, 0x64, 0xfc,
419 0x27, 0x0c, 0x26, 0x38, 0x2b, 0xf3, 0x15, 0xc1, 0x9e, 0x97, 0xa7, 0x61,
420 0x04, 0xa7, 0x16, 0xfc, 0x99, 0x8a, 0x65, 0x1e, 0x86, 0x10, 0xa3, 0xae,
421 0x6c, 0xf6, 0x5d, 0x8f, 0xae, 0x5d, 0x3f, 0x32, 0xee, 0xa0, 0x0b, 0x32,
422 0xcb, 0x96, 0x09, 0xb4, 0x94, 0x11, 0x6a, 0x82, 0x5d, 0x71, 0x42, 0xd1,
423 0x7b, 0x88, 0xe3, 0xd2, 0x0e, 0xdd, 0x98, 0x74, 0x3d, 0xe2, 0x9c, 0xf3,
424 0x7a, 0x23, 0xa9, 0xf6, 0xa5, 0x8b, 0x96, 0x05, 0x91, 0x31, 0x57, 0xd5,
425 0x96, 0x5f, 0xcb, 0x46, 0xdd, 0xa7, 0x3a, 0x1f, 0x08, 0xdd, 0x89, 0x7b,
426 0xae, 0x88, 0xdf, 0xe6, 0xfc, 0x93, 0x7c, 0xba
428 static const uint8_t peer_public_key[] = {
429 0x58, 0x66, 0x05, 0x49, 0x94, 0x23, 0x2b, 0x66, 0x52, 0x13, 0xff, 0x46,
430 0xf2, 0xb3, 0x79, 0xa9, 0xee, 0xae, 0x1a, 0x13, 0xf0, 0x71, 0x52, 0xfb,
431 0x93, 0x4e, 0xee, 0x97, 0x05, 0x73, 0x50, 0x7d, 0xaf, 0x02, 0x07, 0x72,
432 0xac, 0xdc, 0xa3, 0x95, 0x78, 0xee, 0x9a, 0x19, 0x71, 0x7e, 0x99, 0x9f,
433 0x2a, 0xd4, 0xb3, 0xe2, 0x0c, 0x1d, 0x1a, 0x78, 0x4c, 0xde, 0xf1, 0xad,
434 0xb4, 0x60, 0xa8, 0x51, 0xac, 0x71, 0xec, 0x86, 0x70, 0xa2, 0x63, 0x36,
435 0x92, 0x7c, 0xe3, 0x87, 0xee, 0xe4, 0xf1, 0x62, 0x24, 0x74, 0xb4, 0x04,
436 0xfa, 0x5c, 0xdf, 0xba, 0xfa, 0xa3, 0xc2, 0xbb, 0x62, 0x27, 0xd0, 0xf4,
437 0xe4, 0x43, 0xda, 0x8a, 0x88, 0x69, 0x60, 0xe2, 0xdb, 0x75, 0x2a, 0x98,
438 0x9d, 0xb5, 0x50, 0xe3, 0x99, 0xda, 0xe0, 0xa6, 0x14, 0xc9, 0x80, 0x12,
439 0xf9, 0x3c, 0xac, 0x06, 0x02, 0x7a, 0xde, 0x74
441 static const uint8_t shared_secret[] = {
442 0xb2, 0xeb, 0xcb, 0x71, 0xf3, 0x61, 0xfb, 0x5b, 0x4e, 0x5c, 0x4c, 0xcf,
443 0x5c, 0x08, 0x5f, 0x96, 0x26, 0x77, 0x1d, 0x31, 0xf1, 0xe1, 0xf7, 0x4b,
444 0x92, 0xac, 0x82, 0x2a, 0x88, 0xc7, 0x83, 0xe1, 0xc7, 0xf3, 0xd3, 0x1a,
445 0x7d, 0xc8, 0x31, 0xe3, 0x97, 0xe4, 0xec, 0x31, 0x0e, 0x8f, 0x73, 0x1a,
446 0xe4, 0xf6, 0xd8, 0xc8, 0x94, 0xff, 0xa0, 0x03, 0x84, 0x03, 0x0f, 0xa5,
447 0x30, 0x5d, 0x67, 0xe0, 0x7a, 0x3b, 0x5f, 0xed, 0x4c, 0xf5, 0xbc, 0x18,
448 0xea, 0xd4, 0x77, 0xa9, 0x07, 0xb3, 0x54, 0x0b, 0x02, 0xd9, 0xc6, 0xb8,
449 0x66, 0x5e, 0xec, 0xa4, 0xcd, 0x47, 0xed, 0xc9, 0x38, 0xc6, 0x91, 0x08,
450 0xf3, 0x85, 0x9b, 0x69, 0x16, 0x78, 0x0d, 0xb7, 0x74, 0x51, 0xaa, 0x5b,
451 0x4d, 0x74, 0xe4, 0x29, 0x2e, 0x9e, 0x8e, 0xf7, 0xe5, 0x42, 0x83, 0xb0,
452 0x65, 0xb0, 0xce, 0xc6, 0xb2, 0x8f, 0x5b, 0xb0
455 static int test_ref_data(
void)
465 bn_hex2bn(dh->priv_key, private_key, ret);
468 bn_hex2bn(dh->pub_key, public_key, ret);
473 if (memcmp(pubkey_test, public_key_bin,
sizeof(pubkey_test))) {
474 printf(
"Mismatched generated public key\n");
478 printf(
"Generated public key ok\n");
481 sharedkey_test,
sizeof(sharedkey_test))) < 0)
483 if (memcmp(shared_secret, sharedkey_test,
sizeof(sharedkey_test))) {
484 printf(
"Mismatched generated shared key\n");
487 printf(
"Generated shared key ok\n");
496 if (test_random_shared_secret() < 0)
498 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)