diff options
author | Christian Grothoff <christian@grothoff.org> | 2018-05-17 11:29:41 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2018-05-17 11:29:41 +0200 |
commit | 3175cde841a8a7836fcf74a3e1b804c71a3aa153 (patch) | |
tree | 9995eed6c318b9b6fe1833b5e30bd37111668250 /src/util/crypto_ecc.c | |
parent | 20fe42aac530cadfd88e5e409184b361a7f14f8f (diff) | |
download | gnunet-3175cde841a8a7836fcf74a3e1b804c71a3aa153.tar.gz gnunet-3175cde841a8a7836fcf74a3e1b804c71a3aa153.zip |
deduplicate code in crypto_ecc
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r-- | src/util/crypto_ecc.c | 137 |
1 files changed, 58 insertions, 79 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index 5d5e8a9ce..8cc6c18cb 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c | |||
@@ -1279,6 +1279,48 @@ eddsa_d_to_a (gcry_mpi_t d) | |||
1279 | 1279 | ||
1280 | 1280 | ||
1281 | /** | 1281 | /** |
1282 | * Take point from ECDH and convert it to key material. | ||
1283 | * | ||
1284 | * @param result point from ECDH | ||
1285 | * @param ctx ECC context | ||
1286 | * @param key_material[out] set to derived key material | ||
1287 | * @return #GNUNET_OK on success | ||
1288 | */ | ||
1289 | static int | ||
1290 | point_to_hash (gcry_mpi_point_t result, | ||
1291 | gcry_ctx_t ctx, | ||
1292 | struct GNUNET_HashCode *key_material) | ||
1293 | { | ||
1294 | gcry_mpi_t result_x; | ||
1295 | unsigned char xbuf[256 / 8]; | ||
1296 | size_t rsize; | ||
1297 | |||
1298 | /* finally, convert point to string for hashing */ | ||
1299 | result_x = gcry_mpi_new (256); | ||
1300 | if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) | ||
1301 | { | ||
1302 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); | ||
1303 | return GNUNET_SYSERR; | ||
1304 | } | ||
1305 | |||
1306 | rsize = sizeof (xbuf); | ||
1307 | GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); | ||
1308 | /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' | ||
1309 | as that does not include the sign bit; x should be a 255-bit | ||
1310 | value, so with the sign it should fit snugly into the 256-bit | ||
1311 | xbuf */ | ||
1312 | GNUNET_assert (0 == | ||
1313 | gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, | ||
1314 | result_x)); | ||
1315 | GNUNET_CRYPTO_hash (xbuf, | ||
1316 | rsize, | ||
1317 | key_material); | ||
1318 | gcry_mpi_release (result_x); | ||
1319 | return GNUNET_OK; | ||
1320 | } | ||
1321 | |||
1322 | |||
1323 | /** | ||
1282 | * @ingroup crypto | 1324 | * @ingroup crypto |
1283 | * Derive key material from a ECDH public key and a private EdDSA key. | 1325 | * Derive key material from a ECDH public key and a private EdDSA key. |
1284 | * Dual to #GNUNET_CRRYPTO_ecdh_eddsa. | 1326 | * Dual to #GNUNET_CRRYPTO_ecdh_eddsa. |
@@ -1299,9 +1341,7 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, | |||
1299 | gcry_mpi_t a; | 1341 | gcry_mpi_t a; |
1300 | gcry_ctx_t ctx; | 1342 | gcry_ctx_t ctx; |
1301 | gcry_sexp_t pub_sexpr; | 1343 | gcry_sexp_t pub_sexpr; |
1302 | gcry_mpi_t result_x; | 1344 | int ret; |
1303 | unsigned char xbuf[256 / 8]; | ||
1304 | size_t rsize; | ||
1305 | 1345 | ||
1306 | /* first, extract the q = dP value from the public key */ | 1346 | /* first, extract the q = dP value from the public key */ |
1307 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, | 1347 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, |
@@ -1325,34 +1365,15 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, | |||
1325 | gcry_mpi_point_release (q); | 1365 | gcry_mpi_point_release (q); |
1326 | gcry_mpi_release (a); | 1366 | gcry_mpi_release (a); |
1327 | 1367 | ||
1328 | /* finally, convert point to string for hashing */ | 1368 | ret = point_to_hash (result, |
1329 | result_x = gcry_mpi_new (256); | 1369 | ctx, |
1330 | if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) | 1370 | key_material); |
1331 | { | ||
1332 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); | ||
1333 | gcry_mpi_point_release (result); | ||
1334 | gcry_ctx_release (ctx); | ||
1335 | return GNUNET_SYSERR; | ||
1336 | } | ||
1337 | gcry_mpi_point_release (result); | 1371 | gcry_mpi_point_release (result); |
1338 | gcry_ctx_release (ctx); | 1372 | gcry_ctx_release (ctx); |
1339 | 1373 | return ret; | |
1340 | rsize = sizeof (xbuf); | ||
1341 | GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); | ||
1342 | /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' | ||
1343 | as that does not include the sign bit; x should be a 255-bit | ||
1344 | value, so with the sign it should fit snugly into the 256-bit | ||
1345 | xbuf */ | ||
1346 | GNUNET_assert (0 == | ||
1347 | gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, | ||
1348 | result_x)); | ||
1349 | GNUNET_CRYPTO_hash (xbuf, | ||
1350 | rsize, | ||
1351 | key_material); | ||
1352 | gcry_mpi_release (result_x); | ||
1353 | return GNUNET_OK; | ||
1354 | } | 1374 | } |
1355 | 1375 | ||
1376 | |||
1356 | /** | 1377 | /** |
1357 | * @ingroup crypto | 1378 | * @ingroup crypto |
1358 | * Derive key material from a ECDH public key and a private ECDSA key. | 1379 | * Derive key material from a ECDH public key and a private ECDSA key. |
@@ -1373,9 +1394,7 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | |||
1373 | gcry_mpi_t d; | 1394 | gcry_mpi_t d; |
1374 | gcry_ctx_t ctx; | 1395 | gcry_ctx_t ctx; |
1375 | gcry_sexp_t pub_sexpr; | 1396 | gcry_sexp_t pub_sexpr; |
1376 | gcry_mpi_t result_x; | 1397 | int ret; |
1377 | unsigned char xbuf[256 / 8]; | ||
1378 | size_t rsize; | ||
1379 | 1398 | ||
1380 | /* first, extract the q = dP value from the public key */ | 1399 | /* first, extract the q = dP value from the public key */ |
1381 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, | 1400 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, |
@@ -1396,31 +1415,12 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | |||
1396 | gcry_mpi_release (d); | 1415 | gcry_mpi_release (d); |
1397 | 1416 | ||
1398 | /* finally, convert point to string for hashing */ | 1417 | /* finally, convert point to string for hashing */ |
1399 | result_x = gcry_mpi_new (256); | 1418 | ret = point_to_hash (result, |
1400 | if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) | 1419 | ctx, |
1401 | { | 1420 | key_material); |
1402 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); | ||
1403 | gcry_mpi_point_release (result); | ||
1404 | gcry_ctx_release (ctx); | ||
1405 | return GNUNET_SYSERR; | ||
1406 | } | ||
1407 | gcry_mpi_point_release (result); | 1421 | gcry_mpi_point_release (result); |
1408 | gcry_ctx_release (ctx); | 1422 | gcry_ctx_release (ctx); |
1409 | 1423 | return ret; | |
1410 | rsize = sizeof (xbuf); | ||
1411 | GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); | ||
1412 | /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' | ||
1413 | as that does not include the sign bit; x should be a 255-bit | ||
1414 | value, so with the sign it should fit snugly into the 256-bit | ||
1415 | xbuf */ | ||
1416 | GNUNET_assert (0 == | ||
1417 | gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, | ||
1418 | result_x)); | ||
1419 | GNUNET_CRYPTO_hash (xbuf, | ||
1420 | rsize, | ||
1421 | key_material); | ||
1422 | gcry_mpi_release (result_x); | ||
1423 | return GNUNET_OK; | ||
1424 | } | 1424 | } |
1425 | 1425 | ||
1426 | 1426 | ||
@@ -1445,9 +1445,7 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | |||
1445 | gcry_mpi_t d; | 1445 | gcry_mpi_t d; |
1446 | gcry_ctx_t ctx; | 1446 | gcry_ctx_t ctx; |
1447 | gcry_sexp_t pub_sexpr; | 1447 | gcry_sexp_t pub_sexpr; |
1448 | gcry_mpi_t result_x; | 1448 | int ret; |
1449 | unsigned char xbuf[256 / 8]; | ||
1450 | size_t rsize; | ||
1451 | 1449 | ||
1452 | /* first, extract the q = dP value from the public key */ | 1450 | /* first, extract the q = dP value from the public key */ |
1453 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, | 1451 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, |
@@ -1468,31 +1466,12 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | |||
1468 | gcry_mpi_release (d); | 1466 | gcry_mpi_release (d); |
1469 | 1467 | ||
1470 | /* finally, convert point to string for hashing */ | 1468 | /* finally, convert point to string for hashing */ |
1471 | result_x = gcry_mpi_new (256); | 1469 | ret = point_to_hash (result, |
1472 | if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) | 1470 | ctx, |
1473 | { | 1471 | key_material); |
1474 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); | ||
1475 | gcry_mpi_point_release (result); | ||
1476 | gcry_ctx_release (ctx); | ||
1477 | return GNUNET_SYSERR; | ||
1478 | } | ||
1479 | gcry_mpi_point_release (result); | 1472 | gcry_mpi_point_release (result); |
1480 | gcry_ctx_release (ctx); | 1473 | gcry_ctx_release (ctx); |
1481 | 1474 | return ret; | |
1482 | rsize = sizeof (xbuf); | ||
1483 | GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); | ||
1484 | /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' | ||
1485 | as that does not include the sign bit; x should be a 255-bit | ||
1486 | value, so with the sign it should fit snugly into the 256-bit | ||
1487 | xbuf */ | ||
1488 | GNUNET_assert (0 == | ||
1489 | gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, | ||
1490 | result_x)); | ||
1491 | GNUNET_CRYPTO_hash (xbuf, | ||
1492 | rsize, | ||
1493 | key_material); | ||
1494 | gcry_mpi_release (result_x); | ||
1495 | return GNUNET_OK; | ||
1496 | } | 1475 | } |
1497 | 1476 | ||
1498 | /** | 1477 | /** |