aboutsummaryrefslogtreecommitdiff
path: root/src/util/crypto_ecc.c
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2013-08-07 21:27:39 +0000
committerChristian Grothoff <christian@grothoff.org>2013-08-07 21:27:39 +0000
commit86032069a343d87fe79c8cb7d05a975dc81c2d70 (patch)
treeba80da3a173977890ca03c55793ee64bde3d8d73 /src/util/crypto_ecc.c
parent1fb28e00ee7b770049328a9d880b00f553599e9a (diff)
downloadgnunet-86032069a343d87fe79c8cb7d05a975dc81c2d70.tar.gz
gnunet-86032069a343d87fe79c8cb7d05a975dc81c2d70.zip
-testcase for new ECC crypto functions
Diffstat (limited to 'src/util/crypto_ecc.c')
-rw-r--r--src/util/crypto_ecc.c115
1 files changed, 38 insertions, 77 deletions
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c
index 122c1857d..1569c6a23 100644
--- a/src/util/crypto_ecc.c
+++ b/src/util/crypto_ecc.c
@@ -203,19 +203,18 @@ decode_private_key (const struct GNUNET_CRYPTO_EccPrivateKey *priv)
203{ 203{
204 gcry_sexp_t result; 204 gcry_sexp_t result;
205 gcry_mpi_t d; 205 gcry_mpi_t d;
206 size_t erroff;
207 int rc; 206 int rc;
208 207
209 mpi_scan (&d, 208 mpi_scan (&d,
210 priv->d, 209 priv->d,
211 sizeof (priv->d)); 210 sizeof (priv->d));
212 rc = gcry_sexp_build (&result, &erroff, 211 rc = gcry_sexp_build (&result, NULL,
213 "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))", 212 "(private-key(ecdsa(curve \"" CURVE "\")(d %m)))",
214 d); 213 d);
215 gcry_mpi_release (d); 214 gcry_mpi_release (d);
216 if (0 != rc) 215 if (0 != rc)
217 { 216 {
218 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ 217 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
219 GNUNET_assert (0); 218 GNUNET_assert (0);
220 } 219 }
221#if EXTRA_CHECKS 220#if EXTRA_CHECKS
@@ -244,7 +243,7 @@ point_to_public_key (gcry_mpi_point_t q,
244{ 243{
245 gcry_mpi_t q_x; 244 gcry_mpi_t q_x;
246 gcry_mpi_t q_y; 245 gcry_mpi_t q_y;
247 246
248 q_x = gcry_mpi_new (256); 247 q_x = gcry_mpi_new (256);
249 q_y = gcry_mpi_new (256); 248 q_y = gcry_mpi_new (256);
250 if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx)) 249 if (gcry_mpi_ec_get_affine (q_x, q_y, q, ctx))
@@ -272,15 +271,10 @@ GNUNET_CRYPTO_ecc_key_get_public (const struct GNUNET_CRYPTO_EccPrivateKey *priv
272 gcry_sexp_t sexp; 271 gcry_sexp_t sexp;
273 gcry_ctx_t ctx; 272 gcry_ctx_t ctx;
274 gcry_mpi_point_t q; 273 gcry_mpi_point_t q;
275 int rc;
276 274
277 sexp = decode_private_key (priv); 275 sexp = decode_private_key (priv);
278 GNUNET_assert (NULL != sexp); 276 GNUNET_assert (NULL != sexp);
279 if (0 != (rc = gcry_mpi_ec_new (&ctx, sexp, NULL))) 277 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
280 {
281 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
282 return;
283 }
284 gcry_sexp_release (sexp); 278 gcry_sexp_release (sexp);
285 q = gcry_mpi_ec_get_point ("q", ctx, 0); 279 q = gcry_mpi_ec_get_point ("q", ctx, 0);
286 point_to_public_key (q, ctx, pub); 280 point_to_public_key (q, ctx, pub);
@@ -364,7 +358,6 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKey *pub)
364 gcry_mpi_t q_y; 358 gcry_mpi_t q_y;
365 gcry_mpi_point_t q; 359 gcry_mpi_point_t q;
366 gcry_ctx_t ctx; 360 gcry_ctx_t ctx;
367 int rc;
368 361
369 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x)); 362 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
370 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y)); 363 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
@@ -373,24 +366,13 @@ decode_public_key (const struct GNUNET_CRYPTO_EccPublicKey *pub)
373 gcry_mpi_release (q_x); 366 gcry_mpi_release (q_x);
374 gcry_mpi_release (q_y); 367 gcry_mpi_release (q_y);
375 368
376 /* create basic ECC context */
377 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, CURVE)))
378 {
379 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
380 gcry_mpi_point_release (q);
381 return NULL;
382 }
383 /* initialize 'ctx' with 'q' */ 369 /* initialize 'ctx' with 'q' */
370 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
384 gcry_mpi_ec_set_point ("q", q, ctx); 371 gcry_mpi_ec_set_point ("q", q, ctx);
385 gcry_mpi_point_release (q); 372 gcry_mpi_point_release (q);
386 373
387 /* convert 'ctx' to 'sexp' */ 374 /* convert 'ctx' to 'sexp' */
388 if (0 != (rc = gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx))) 375 GNUNET_assert (0 == gcry_pubkey_get_sexp (&pub_sexp, GCRY_PK_GET_PUBKEY, ctx));
389 {
390 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_from_context", rc);
391 gcry_ctx_release (ctx);
392 return NULL;
393 }
394 gcry_ctx_release (ctx); 376 gcry_ctx_release (ctx);
395 return pub_sexp; 377 return pub_sexp;
396} 378}
@@ -438,7 +420,7 @@ GNUNET_CRYPTO_ecc_key_create ()
438 return NULL; 420 return NULL;
439 } 421 }
440 gcry_sexp_release (priv_sexp); 422 gcry_sexp_release (priv_sexp);
441 priv = GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccPrivateKey)); 423 priv = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
442 mpi_print (priv->d, sizeof (priv->d), d); 424 mpi_print (priv->d, sizeof (priv->d), d);
443 gcry_mpi_release (d); 425 gcry_mpi_release (d);
444 return priv; 426 return priv;
@@ -521,7 +503,7 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename)
521 GNUNET_DISK_PERM_USER_WRITE); 503 GNUNET_DISK_PERM_USER_WRITE);
522 if (NULL == fd) 504 if (NULL == fd)
523 { 505 {
524 if (errno == EEXIST) 506 if (EEXIST == errno)
525 { 507 {
526 if (GNUNET_YES != GNUNET_DISK_file_test (filename)) 508 if (GNUNET_YES != GNUNET_DISK_file_test (filename))
527 { 509 {
@@ -538,7 +520,6 @@ GNUNET_CRYPTO_ecc_key_create_from_file (const char *filename)
538 return NULL; 520 return NULL;
539 } 521 }
540 cnt = 0; 522 cnt = 0;
541
542 while (GNUNET_YES != 523 while (GNUNET_YES !=
543 GNUNET_DISK_file_lock (fd, 0, 524 GNUNET_DISK_file_lock (fd, 0,
544 sizeof (struct GNUNET_CRYPTO_EccPrivateKey), 525 sizeof (struct GNUNET_CRYPTO_EccPrivateKey),
@@ -816,7 +797,6 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
816 gcry_sexp_t data; 797 gcry_sexp_t data;
817 gcry_sexp_t sig_sexpr; 798 gcry_sexp_t sig_sexpr;
818 gcry_sexp_t pub_sexpr; 799 gcry_sexp_t pub_sexpr;
819 size_t erroff;
820 int rc; 800 int rc;
821 gcry_mpi_t r; 801 gcry_mpi_t r;
822 gcry_mpi_t s; 802 gcry_mpi_t s;
@@ -827,7 +807,8 @@ GNUNET_CRYPTO_ecc_verify (uint32_t purpose,
827 /* build s-expression for signature */ 807 /* build s-expression for signature */
828 mpi_scan (&r, sig->r, sizeof (sig->r)); 808 mpi_scan (&r, sig->r, sizeof (sig->r));
829 mpi_scan (&s, sig->s, sizeof (sig->s)); 809 mpi_scan (&s, sig->s, sizeof (sig->s));
830 if (0 != (rc = gcry_sexp_build (&sig_sexpr, &erroff, "(sig-val(ecdsa(r %m)(s %m)))", 810 if (0 != (rc = gcry_sexp_build (&sig_sexpr, NULL,
811 "(sig-val(ecdsa(r %m)(s %m)))",
831 r, s))) 812 r, s)))
832 { 813 {
833 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); 814 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
@@ -873,9 +854,9 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *priv,
873 struct GNUNET_HashCode *key_material) 854 struct GNUNET_HashCode *key_material)
874{ 855{
875 size_t slen; 856 size_t slen;
876 size_t erroff; 857 unsigned char sdata_buf[2048]; /* big enough to print
877 int rc; 858 dh-shared-secret as
878 unsigned char sdata_buf[2048]; /* big enough to print dh-shared-secret as S-expression */ 859 S-expression */
879 gcry_mpi_point_t result; 860 gcry_mpi_point_t result;
880 gcry_mpi_point_t q; 861 gcry_mpi_point_t q;
881 gcry_mpi_t d; 862 gcry_mpi_t d;
@@ -884,34 +865,19 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *priv,
884 gcry_sexp_t ecdh_sexp; 865 gcry_sexp_t ecdh_sexp;
885 gcry_mpi_t result_x; 866 gcry_mpi_t result_x;
886 gcry_mpi_t result_y; 867 gcry_mpi_t result_y;
868 int rc;
887 869
888 /* first, extract the q = dP value from the public key */ 870 /* first, extract the q = dP value from the public key */
889 if (! (pub_sexpr = decode_public_key (pub))) 871 if (! (pub_sexpr = decode_public_key (pub)))
890 return GNUNET_SYSERR; 872 return GNUNET_SYSERR;
891 if (0 != (rc = gcry_mpi_ec_new (&ctx, pub_sexpr, NULL))) 873 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL));
892 {
893 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
894 return GNUNET_SYSERR;
895 }
896 gcry_sexp_release (pub_sexpr); 874 gcry_sexp_release (pub_sexpr);
897 q = gcry_mpi_ec_get_point ("q", ctx, 0); 875 q = gcry_mpi_ec_get_point ("q", ctx, 0);
898 gcry_ctx_release (ctx);
899 876
900 /* second, extract the d value from our private key */ 877 /* second, extract the d value from our private key */
901 mpi_scan (&d, priv->d, sizeof (priv->d)); 878 mpi_scan (&d, priv->d, sizeof (priv->d));
902 879
903 /* create a new context for definitively the correct curve;
904 theoretically the 'public_key' might not use the right curve */
905 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, CURVE)))
906 {
907 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); /* erroff gives more info */
908 gcry_mpi_release (d);
909 gcry_mpi_point_release (q);
910 return GNUNET_SYSERR;
911 }
912
913 /* then call the 'multiply' function, to compute the product */ 880 /* then call the 'multiply' function, to compute the product */
914 GNUNET_assert (NULL != ctx);
915 result = gcry_mpi_point_new (0); 881 result = gcry_mpi_point_new (0);
916 gcry_mpi_ec_mul (result, d, q, ctx); 882 gcry_mpi_ec_mul (result, d, q, ctx);
917 gcry_mpi_point_release (q); 883 gcry_mpi_point_release (q);
@@ -929,12 +895,12 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EccPrivateKey *priv,
929 } 895 }
930 gcry_mpi_point_release (result); 896 gcry_mpi_point_release (result);
931 gcry_ctx_release (ctx); 897 gcry_ctx_release (ctx);
932 if (0 != (rc = gcry_sexp_build (&ecdh_sexp, &erroff, 898 if (0 != (rc = gcry_sexp_build (&ecdh_sexp, NULL,
933 "(dh-shared-secret (x %m)(y %m))", 899 "(dh-shared-secret (x %m)(y %m))",
934 result_x, 900 result_x,
935 result_y))) 901 result_y)))
936 { 902 {
937 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc); /* erroff gives more info */ 903 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
938 gcry_mpi_release (result_x); 904 gcry_mpi_release (result_x);
939 gcry_mpi_release (result_y); 905 gcry_mpi_release (result_y);
940 return GNUNET_SYSERR; 906 return GNUNET_SYSERR;
@@ -998,24 +964,17 @@ GNUNET_CRYPTO_ecc_key_derive (const struct GNUNET_CRYPTO_EccPrivateKey *priv,
998 gcry_mpi_t x; 964 gcry_mpi_t x;
999 gcry_mpi_t d; 965 gcry_mpi_t d;
1000 gcry_mpi_t n; 966 gcry_mpi_t n;
1001 int rc; 967 gcry_ctx_t ctx;
1002 968
969 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
970 n = gcry_mpi_ec_get_mpi ("n", ctx, 0 /* no copy */);
1003 GNUNET_CRYPTO_ecc_key_get_public (priv, &pub); 971 GNUNET_CRYPTO_ecc_key_get_public (priv, &pub);
1004 h = derive_h (&pub, label); 972 h = derive_h (&pub, label);
1005 mpi_scan (&x, priv->d, sizeof (priv->d)); 973 mpi_scan (&x, priv->d, sizeof (priv->d));
1006 /* initialize 'n' from P-256; hex copied from libgcrypt code */
1007 if (0 != (rc = gcry_mpi_scan (&n, GCRYMPI_FMT_HEX,
1008 "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551", 0, NULL)))
1009 {
1010 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_scan", rc);
1011 gcry_mpi_release (h);
1012 return NULL;
1013 }
1014 d = gcry_mpi_new (256); 974 d = gcry_mpi_new (256);
1015 gcry_mpi_mulm (d, h, x, n); 975 gcry_mpi_mulm (d, h, x, n);
1016 gcry_mpi_release (h); 976 gcry_mpi_release (h);
1017 gcry_mpi_release (x); 977 gcry_mpi_release (x);
1018 gcry_mpi_release (n);
1019 ret = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey); 978 ret = GNUNET_new (struct GNUNET_CRYPTO_EccPrivateKey);
1020 mpi_print (ret->d, sizeof (ret->d), d); 979 mpi_print (ret->d, sizeof (ret->d), d);
1021 gcry_mpi_release (d); 980 gcry_mpi_release (d);
@@ -1036,36 +995,38 @@ GNUNET_CRYPTO_ecc_public_key_derive (const struct GNUNET_CRYPTO_EccPublicKey *pu
1036 const char *label, 995 const char *label,
1037 struct GNUNET_CRYPTO_EccPublicKey *result) 996 struct GNUNET_CRYPTO_EccPublicKey *result)
1038{ 997{
1039 gcry_mpi_t h;
1040 gcry_ctx_t ctx; 998 gcry_ctx_t ctx;
999 gcry_mpi_t h;
1000 gcry_mpi_t n;
1001 gcry_mpi_t h_mod_n;
1041 gcry_mpi_t q_x; 1002 gcry_mpi_t q_x;
1042 gcry_mpi_t q_y; 1003 gcry_mpi_t q_y;
1043 gcry_mpi_point_t q; 1004 gcry_mpi_point_t q;
1044 gcry_mpi_point_t v; 1005 gcry_mpi_point_t v;
1045 int rc;
1046 1006
1047 h = derive_h (pub, label); 1007 GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, CURVE));
1008
1009 /* obtain point 'q' from original public key */
1048 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x)); 1010 mpi_scan (&q_x, pub->q_x, sizeof (pub->q_x));
1049 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y)); 1011 mpi_scan (&q_y, pub->q_y, sizeof (pub->q_y));
1050 q = gcry_mpi_point_new (256); 1012
1013 q = gcry_mpi_point_new (0);
1051 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE); 1014 gcry_mpi_point_set (q, q_x, q_y, GCRYMPI_CONST_ONE);
1052 gcry_mpi_release (q_x); 1015 gcry_mpi_release (q_x);
1053 gcry_mpi_release (q_y); 1016 gcry_mpi_release (q_y);
1054 1017
1055 /* create basic ECC context */ 1018 /* calulcate h_mod_n = h % n */
1056 if (0 != (rc = gcry_mpi_ec_new (&ctx, NULL, CURVE))) 1019 h = derive_h (pub, label);
1057 { 1020 n = gcry_mpi_ec_get_mpi ("n", ctx, 0 /* no copy */);
1058 LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_mpi_ec_new", rc); 1021 h_mod_n = gcry_mpi_new (256);
1059 gcry_mpi_point_release (q); 1022 gcry_mpi_mod (h_mod_n, h, n);
1060 gcry_mpi_release (h); 1023 /* calculate v = h_mod_n * q */
1061 return; 1024 v = gcry_mpi_point_new (0);
1062 } 1025 gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
1063 v = gcry_mpi_point_new (256); 1026 gcry_mpi_release (h_mod_n);
1064 /* we could calculate 'h mod n' here first, but hopefully
1065 libgcrypt is smart enough to do that for us... */
1066 gcry_mpi_ec_mul (v, h, q, ctx);
1067 gcry_mpi_release (h); 1027 gcry_mpi_release (h);
1068 gcry_mpi_point_release (q); 1028 gcry_mpi_point_release (q);
1029 /* convert point 'v' to public key that we return */
1069 point_to_public_key (v, ctx, result); 1030 point_to_public_key (v, ctx, result);
1070 gcry_mpi_point_release (v); 1031 gcry_mpi_point_release (v);
1071 gcry_ctx_release (ctx); 1032 gcry_ctx_release (ctx);