diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2016-01-04 12:43:47 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2016-01-04 12:43:47 +0000 |
commit | 588c1bd23e49f3264bdfdb3b02c7cf6e78b66534 (patch) | |
tree | 2fe3b1f9e930a75675eb7e75aaab5100cb13ab54 /src | |
parent | 1af781131216a54772885e8514d5a9c9ef2f6cd0 (diff) | |
download | gnunet-588c1bd23e49f3264bdfdb3b02c7cf6e78b66534.tar.gz gnunet-588c1bd23e49f3264bdfdb3b02c7cf6e78b66534.zip |
- Add ecdsa ecdh functions
- Update identity token to encrypted protocol
Diffstat (limited to 'src')
-rw-r--r-- | src/identity-token/gnunet-service-identity-token.c | 2 | ||||
-rw-r--r-- | src/identity-token/plugin_rest_identity_token.c | 499 | ||||
-rw-r--r-- | src/include/gnunet_crypto_lib.h | 30 | ||||
-rw-r--r-- | src/include/gnunet_signatures.h | 5 | ||||
-rw-r--r-- | src/util/crypto_ecc.c | 91 |
5 files changed, 532 insertions, 95 deletions
diff --git a/src/identity-token/gnunet-service-identity-token.c b/src/identity-token/gnunet-service-identity-token.c index 222b9d184..5fcf47e14 100644 --- a/src/identity-token/gnunet-service-identity-token.c +++ b/src/identity-token/gnunet-service-identity-token.c | |||
@@ -188,7 +188,7 @@ handle_token_update (void *cls, | |||
188 | char *new_payload_str; | 188 | char *new_payload_str; |
189 | char *new_payload_base64; | 189 | char *new_payload_base64; |
190 | char *sig_str; | 190 | char *sig_str; |
191 | char *key; | 191 | const char *key; |
192 | char *padding; | 192 | char *padding; |
193 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 193 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; |
194 | struct EgoEntry *ego_entry = cls; | 194 | struct EgoEntry *ego_entry = cls; |
diff --git a/src/identity-token/plugin_rest_identity_token.c b/src/identity-token/plugin_rest_identity_token.c index 6b9106e14..2621d1f57 100644 --- a/src/identity-token/plugin_rest_identity_token.c +++ b/src/identity-token/plugin_rest_identity_token.c | |||
@@ -51,21 +51,23 @@ | |||
51 | #define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/gnuid/check" | 51 | #define GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK "/gnuid/check" |
52 | 52 | ||
53 | /** | 53 | /** |
54 | * OAuth2 namespace | 54 | * Token namespace |
55 | */ | 55 | */ |
56 | #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/gnuid/token" | 56 | #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN "/gnuid/token" |
57 | 57 | ||
58 | /** | 58 | /** |
59 | * OAuth2 namespace | 59 | * Authorize namespace |
60 | */ | 60 | */ |
61 | #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_AUTHORIZE "/gnuid/authorize" | 61 | #define GNUNET_REST_API_NS_IDENTITY_OAUTH2_AUTHORIZE "/gnuid/authorize" |
62 | 62 | ||
63 | #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_CODE "code" | 63 | #define GNUNET_REST_JSONAPI_IDENTITY_TOKEN_CODE "code" |
64 | 64 | ||
65 | #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE_CODE "authorization_code" | 65 | #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE_CODE "authorization_code" |
66 | 66 | ||
67 | #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE "grant_type" | 67 | #define GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_GRANT_TYPE "grant_type" |
68 | 68 | ||
69 | #define GNUNET_IDENTITY_TOKEN_REQUEST_NONCE "nonce" | ||
70 | |||
69 | /** | 71 | /** |
70 | * State while collecting all egos | 72 | * State while collecting all egos |
71 | */ | 73 | */ |
@@ -412,6 +414,88 @@ store_token_cont (void *cls, | |||
412 | GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle); | 414 | GNUNET_SCHEDULER_add_now (&do_cleanup_handle_delayed, handle); |
413 | } | 415 | } |
414 | 416 | ||
417 | static int | ||
418 | create_sym_key_from_ecdh(const struct GNUNET_HashCode *new_key_hash, | ||
419 | struct GNUNET_CRYPTO_SymmetricSessionKey *skey, | ||
420 | struct GNUNET_CRYPTO_SymmetricInitializationVector *iv) | ||
421 | { | ||
422 | struct GNUNET_CRYPTO_HashAsciiEncoded new_key_hash_str; | ||
423 | |||
424 | GNUNET_CRYPTO_hash_to_enc (new_key_hash, | ||
425 | &new_key_hash_str); | ||
426 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Creating symmetric rsa key from %s\n", (char*)&new_key_hash_str); | ||
427 | static const char ctx_key[] = "gnuid-aes-ctx-key"; | ||
428 | GNUNET_CRYPTO_kdf (skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
429 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
430 | ctx_key, strlen (ctx_key), | ||
431 | NULL, 0); | ||
432 | static const char ctx_iv[] = "gnuid-aes-ctx-iv"; | ||
433 | GNUNET_CRYPTO_kdf (iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), | ||
434 | new_key_hash, sizeof (struct GNUNET_HashCode), | ||
435 | ctx_iv, strlen (ctx_iv), | ||
436 | NULL, 0); | ||
437 | return GNUNET_OK; | ||
438 | } | ||
439 | |||
440 | /** | ||
441 | * Create the token code | ||
442 | * The metadata is encrypted with a share ECDH derived secret using B (aud_key) | ||
443 | * and e (ecdh_privkey) | ||
444 | * The token_code also contains E (ecdh_pubkey) and a signature over the | ||
445 | * metadata and E | ||
446 | */ | ||
447 | static int | ||
448 | create_token_code (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, | ||
449 | const struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey, | ||
450 | const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_pubkey, | ||
451 | const char* code_str, | ||
452 | const struct GNUNET_CRYPTO_EcdsaPublicKey *aud_key, | ||
453 | char **result, | ||
454 | size_t *result_len, | ||
455 | struct GNUNET_CRYPTO_EcdsaSignature *sig) | ||
456 | { | ||
457 | char *write_ptr; | ||
458 | struct GNUNET_HashCode new_key_hash; | ||
459 | struct GNUNET_CRYPTO_SymmetricSessionKey skey; | ||
460 | struct GNUNET_CRYPTO_SymmetricInitializationVector iv; | ||
461 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
462 | |||
463 | *result = GNUNET_malloc (strlen (code_str)); | ||
464 | *result_len = strlen (code_str); | ||
465 | |||
466 | // Derived key K = H(eB) | ||
467 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdh_ecdsa (ecdh_privkey, | ||
468 | aud_key, | ||
469 | &new_key_hash)); | ||
470 | create_sym_key_from_ecdh(&new_key_hash, &skey, &iv); | ||
471 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Encrypting token code %s\n", code_str); | ||
472 | GNUNET_CRYPTO_symmetric_encrypt (code_str, strlen (code_str), | ||
473 | &skey, &iv, | ||
474 | *result); | ||
475 | purpose = | ||
476 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
477 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + //E | ||
478 | *result_len); // E_K (code_str) | ||
479 | purpose->size = | ||
480 | htonl (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | ||
481 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey) + | ||
482 | *result_len); | ||
483 | purpose->purpose = htonl(GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN_CODE); | ||
484 | write_ptr = (char*) &purpose[1]; | ||
485 | memcpy (write_ptr, ecdh_pubkey, sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
486 | write_ptr += sizeof (struct GNUNET_CRYPTO_EcdhePublicKey); | ||
487 | memcpy (write_ptr, *result, *result_len); | ||
488 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, | ||
489 | purpose, | ||
490 | sig)) | ||
491 | { | ||
492 | GNUNET_free (purpose); | ||
493 | return GNUNET_SYSERR; | ||
494 | } | ||
495 | GNUNET_free (purpose); | ||
496 | return GNUNET_OK; | ||
497 | } | ||
498 | |||
415 | 499 | ||
416 | /** | 500 | /** |
417 | * Build a GNUid token for identity | 501 | * Build a GNUid token for identity |
@@ -426,6 +510,23 @@ static void | |||
426 | sign_and_return_token (void *cls, | 510 | sign_and_return_token (void *cls, |
427 | const struct GNUNET_SCHEDULER_TaskContext *tc) | 511 | const struct GNUNET_SCHEDULER_TaskContext *tc) |
428 | { | 512 | { |
513 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
514 | |||
515 | struct GNUNET_CRYPTO_EcdsaSignature token_sig; | ||
516 | struct GNUNET_CRYPTO_EcdsaSignature token_code_sig; | ||
517 | struct GNUNET_CRYPTO_EcdsaPublicKey aud_pkey; | ||
518 | struct GNUNET_CRYPTO_EcdhePrivateKey *ecdh_privkey; | ||
519 | struct GNUNET_CRYPTO_EcdhePublicKey ecdh_pubkey; | ||
520 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | ||
521 | struct JsonApiResource *json_resource; | ||
522 | struct RequestHandle *handle = cls; | ||
523 | struct GNUNET_GNSRECORD_Data token_record; | ||
524 | struct GNUNET_HashCode key; | ||
525 | struct GNUNET_TIME_Relative etime_rel; | ||
526 | json_t *token_str; | ||
527 | json_t *name_str; | ||
528 | json_t *token_code_json; | ||
529 | size_t token_code_payload_len; | ||
429 | char *header_str; | 530 | char *header_str; |
430 | char *payload_str; | 531 | char *payload_str; |
431 | char *header_base64; | 532 | char *header_base64; |
@@ -435,23 +536,41 @@ sign_and_return_token (void *cls, | |||
435 | char *token; | 536 | char *token; |
436 | char *exp_str; | 537 | char *exp_str; |
437 | char *renew_str; | 538 | char *renew_str; |
438 | char *rnd_str; | 539 | char *token_code_str; |
540 | char *token_code_payload; | ||
541 | char *code_meta_str; | ||
542 | char *audience; | ||
543 | char *nonce_str; | ||
544 | char *param_str; | ||
545 | char *token_code_sig_str; | ||
546 | char *token_code_payload_str; | ||
547 | char *dh_key_str; | ||
548 | char *record_data; | ||
549 | int renew_token = GNUNET_NO; | ||
439 | uint64_t time; | 550 | uint64_t time; |
440 | uint64_t exp_time; | 551 | uint64_t exp_time; |
441 | uint64_t lbl_key; | 552 | uint64_t rnd_key; |
442 | json_t *token_str; | 553 | |
443 | json_t *name_str; | 554 | //Remote nonce |
444 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | 555 | nonce_str = NULL; |
445 | struct GNUNET_CRYPTO_EcdsaSignature sig; | 556 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE, |
446 | struct GNUNET_CRYPTO_EccSignaturePurpose *purpose; | 557 | strlen (GNUNET_IDENTITY_TOKEN_REQUEST_NONCE), |
447 | struct JsonApiResource *json_resource; | 558 | &key); |
448 | struct RequestHandle *handle = cls; | 559 | if ( GNUNET_YES != |
449 | struct GNUNET_GNSRECORD_Data token_record; | 560 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, |
450 | struct GNUNET_HashCode key; | 561 | &key) ) |
451 | struct GNUNET_TIME_Relative etime_rel; | 562 | { |
452 | int renew_token = GNUNET_NO; | 563 | handle->emsg = GNUNET_strdup ("Request nonce missing!\n"); |
453 | /* | 564 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
454 | //Token audience | 565 | return; |
566 | } | ||
567 | nonce_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | ||
568 | &key); | ||
569 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Request nonce: %s\n", nonce_str); | ||
570 | //Token audience | ||
571 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, | ||
572 | strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), | ||
573 | &key); | ||
455 | audience = NULL; | 574 | audience = NULL; |
456 | if ( GNUNET_YES != | 575 | if ( GNUNET_YES != |
457 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 576 | GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, |
@@ -463,8 +582,9 @@ sign_and_return_token (void *cls, | |||
463 | } | 582 | } |
464 | audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 583 | audience = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, |
465 | &key); | 584 | &key); |
466 | GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Audience to issue token for: %s\n", audience); | 585 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Audience to issue token for: %s\n", audience); |
467 | //Create label for audience | 586 | |
587 | //Audience pubkey (B = bG) | ||
468 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (audience, | 588 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_public_key_from_string (audience, |
469 | strlen (audience), | 589 | strlen (audience), |
470 | &aud_pkey)) | 590 | &aud_pkey)) |
@@ -474,46 +594,51 @@ sign_and_return_token (void *cls, | |||
474 | return; | 594 | return; |
475 | } | 595 | } |
476 | 596 | ||
477 | new_privkey = GNUNET_CRYPTO_ecdhe_key_create(); | ||
478 | |||
479 | GNUNET_CRYPTO_ecdh_ecdsa (new_privkey, | ||
480 | &aud_pkey, | ||
481 | &new_key_hash); | ||
482 | |||
483 | GNUNET_CRYPTO_ecdhe_key_get_public (new_privkey, | ||
484 | new_pubkey); | ||
485 | static const char ctx_key[] = "gnuid-aes-ctx-key"; | ||
486 | GNUNET_CRYPTO_kdf (&skey, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey), | ||
487 | new_pubkey, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), | ||
488 | ctx_key, strlen (ctx_key), | ||
489 | NULL, 0); | ||
490 | static const char ctx_iv[] = "gnuid-aes-ctx-iv"; | ||
491 | GNUNET_CRYPTO_kdf (&iv, sizeof (struct GNUNET_CRYPTO_SymmetricInitializationVector), | ||
492 | new_pubkey, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey), | ||
493 | ctx_iv, strlen (ctx_iv), | ||
494 | NULL, 0); | ||
495 | */ | ||
496 | //TODO: Encrypt the label | ||
497 | time = GNUNET_TIME_absolute_get().abs_value_us; | 597 | time = GNUNET_TIME_absolute_get().abs_value_us; |
498 | lbl_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); | 598 | rnd_key = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_STRONG, UINT64_MAX); |
499 | GNUNET_asprintf (&rnd_str, | 599 | GNUNET_STRINGS_base64_encode ((char*)&rnd_key, sizeof (uint64_t), &lbl_str); |
500 | "{\"nonce\": \"%uul\",\"identity\": \"%s\"}", | 600 | GNUNET_asprintf (&code_meta_str, |
501 | lbl_key, handle->ego_entry->keystring); | 601 | "{\"nonce\": \"%u\",\"identity\": \"%s\",\"label\": \"%s\"}", |
502 | GNUNET_STRINGS_base64_encode (rnd_str, strlen (rnd_str), &lbl_str); | 602 | nonce_str, handle->ego_entry->keystring, lbl_str); |
503 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST, | 603 | priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); |
504 | strlen (GNUNET_REST_JSONAPI_IDENTITY_AUD_REQUEST), | ||
505 | &key); | ||
506 | 604 | ||
507 | /* | 605 | // ECDH keypair E = eG |
508 | GNUNET_CRYPTO_symmetric_encrypt (handle->ego_entry->keystring, strlen (handle->ego_entry->keystring), | 606 | ecdh_privkey = GNUNET_CRYPTO_ecdhe_key_create(); |
509 | &skey, &iv, | 607 | token_code_payload_len = 0; |
510 | &block[1]); | 608 | token_code_payload = NULL; |
609 | GNUNET_CRYPTO_ecdhe_key_get_public (ecdh_privkey, | ||
610 | &ecdh_pubkey); | ||
611 | if (GNUNET_OK != create_token_code (priv_key, | ||
612 | ecdh_privkey, | ||
613 | &ecdh_pubkey, | ||
614 | code_meta_str, | ||
615 | &aud_pkey, | ||
616 | &token_code_payload, | ||
617 | &token_code_payload_len, | ||
618 | &token_code_sig)) | ||
619 | { | ||
620 | handle->emsg = GNUNET_strdup ("Unable to create ref token!\n"); | ||
621 | GNUNET_SCHEDULER_add_now (&do_error, handle); | ||
622 | return; | ||
623 | } | ||
624 | GNUNET_STRINGS_base64_encode (token_code_payload, | ||
625 | token_code_payload_len, | ||
626 | &token_code_payload_str); | ||
627 | token_code_sig_str = GNUNET_STRINGS_data_to_string_alloc (&token_code_sig, | ||
628 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature)); | ||
629 | dh_key_str = GNUNET_STRINGS_data_to_string_alloc (&ecdh_pubkey, | ||
630 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)); | ||
631 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s to encrypt\n", dh_key_str); | ||
632 | GNUNET_asprintf (¶m_str, "{\"meta\": \"%s\", \"ecdh\": \"%s\", \"signature\": \"%s\"}", | ||
633 | token_code_payload_str, dh_key_str, token_code_sig_str); | ||
634 | GNUNET_STRINGS_base64_encode (param_str, strlen (param_str), &token_code_str); | ||
635 | GNUNET_free (param_str); | ||
636 | GNUNET_free (token_code_payload); | ||
637 | GNUNET_free (token_code_payload_str); | ||
511 | 638 | ||
512 | */ | ||
513 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, | 639 | GNUNET_CRYPTO_hash (GNUNET_IDENTITY_TOKEN_EXP_STRING, |
514 | strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), | 640 | strlen (GNUNET_IDENTITY_TOKEN_EXP_STRING), |
515 | &key); | 641 | &key); |
516 | |||
517 | //Get expiration for token from URL parameter | 642 | //Get expiration for token from URL parameter |
518 | exp_str = NULL; | 643 | exp_str = NULL; |
519 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, | 644 | if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map, |
@@ -522,9 +647,6 @@ sign_and_return_token (void *cls, | |||
522 | exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, | 647 | exp_str = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map, |
523 | &key); | 648 | &key); |
524 | } | 649 | } |
525 | |||
526 | |||
527 | |||
528 | if (NULL == exp_str) { | 650 | if (NULL == exp_str) { |
529 | handle->emsg = GNUNET_strdup ("No expiration given!\n"); | 651 | handle->emsg = GNUNET_strdup ("No expiration given!\n"); |
530 | GNUNET_SCHEDULER_add_now (&do_error, handle); | 652 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
@@ -561,6 +683,8 @@ sign_and_return_token (void *cls, | |||
561 | json_object_set_new (handle->payload, "nbf", json_integer (time)); | 683 | json_object_set_new (handle->payload, "nbf", json_integer (time)); |
562 | json_object_set_new (handle->payload, "iat", json_integer (time)); | 684 | json_object_set_new (handle->payload, "iat", json_integer (time)); |
563 | json_object_set_new (handle->payload, "exp", json_integer (exp_time)); | 685 | json_object_set_new (handle->payload, "exp", json_integer (exp_time)); |
686 | json_object_set_new (handle->payload, "nonce", | ||
687 | json_string (nonce_str)); | ||
564 | if (GNUNET_YES == renew_token) | 688 | if (GNUNET_YES == renew_token) |
565 | { | 689 | { |
566 | json_object_set_new (handle->payload, "rnl", json_string ("yes")); | 690 | json_object_set_new (handle->payload, "rnl", json_string ("yes")); |
@@ -583,7 +707,6 @@ sign_and_return_token (void *cls, | |||
583 | padding = strtok(NULL, "="); | 707 | padding = strtok(NULL, "="); |
584 | 708 | ||
585 | GNUNET_asprintf (&token, "%s,%s", header_base64, payload_base64); | 709 | GNUNET_asprintf (&token, "%s,%s", header_base64, payload_base64); |
586 | priv_key = GNUNET_IDENTITY_ego_get_private_key (handle->ego_entry->ego); | ||
587 | purpose = | 710 | purpose = |
588 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + | 711 | GNUNET_malloc (sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + |
589 | strlen (token)); | 712 | strlen (token)); |
@@ -593,10 +716,10 @@ sign_and_return_token (void *cls, | |||
593 | memcpy (&purpose[1], token, strlen (token)); | 716 | memcpy (&purpose[1], token, strlen (token)); |
594 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, | 717 | if (GNUNET_OK != GNUNET_CRYPTO_ecdsa_sign (priv_key, |
595 | purpose, | 718 | purpose, |
596 | &sig)) | 719 | &token_sig)) |
597 | GNUNET_break(0); | 720 | GNUNET_break(0); |
598 | GNUNET_free (token); | 721 | GNUNET_free (token); |
599 | GNUNET_STRINGS_base64_encode ((const char*)&sig, | 722 | GNUNET_STRINGS_base64_encode ((const char*)&token_sig, |
600 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), | 723 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature), |
601 | &sig_str); | 724 | &sig_str); |
602 | GNUNET_asprintf (&token, "%s.%s.%s", | 725 | GNUNET_asprintf (&token, "%s.%s.%s", |
@@ -623,12 +746,20 @@ sign_and_return_token (void *cls, | |||
623 | 746 | ||
624 | 747 | ||
625 | token_str = json_string (token); | 748 | token_str = json_string (token); |
626 | GNUNET_REST_jsonapi_resource_add_attr (json_resource, | 749 | GNUNET_REST_jsonapi_resource_add_attr (json_resource, |
627 | GNUNET_REST_JSONAPI_IDENTITY_TOKEN, | 750 | GNUNET_REST_JSONAPI_IDENTITY_TOKEN, |
628 | token_str); | 751 | token_str); |
752 | token_code_json = json_string (token_code_str); | ||
753 | GNUNET_REST_jsonapi_resource_add_attr (json_resource, | ||
754 | GNUNET_REST_JSONAPI_IDENTITY_TOKEN_CODE, | ||
755 | token_code_json); | ||
756 | GNUNET_free (token_code_str); | ||
757 | json_decref (token_code_json); | ||
629 | GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource); | 758 | GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource); |
630 | token_record.data = token; | 759 | |
631 | token_record.data_size = strlen (token); | 760 | GNUNET_asprintf (&record_data, "%s,%s", dh_key_str, token); |
761 | token_record.data = record_data; | ||
762 | token_record.data_size = strlen (record_data) + 1; | ||
632 | token_record.expiration_time = exp_time; | 763 | token_record.expiration_time = exp_time; |
633 | token_record.record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; | 764 | token_record.record_type = GNUNET_GNSRECORD_TYPE_ID_TOKEN; |
634 | token_record.flags = GNUNET_GNSRECORD_RF_NONE; | 765 | token_record.flags = GNUNET_GNSRECORD_RF_NONE; |
@@ -642,6 +773,7 @@ sign_and_return_token (void *cls, | |||
642 | &token_record, | 773 | &token_record, |
643 | &store_token_cont, | 774 | &store_token_cont, |
644 | handle); | 775 | handle); |
776 | GNUNET_free (record_data); | ||
645 | GNUNET_free (lbl_str); | 777 | GNUNET_free (lbl_str); |
646 | GNUNET_free (token); | 778 | GNUNET_free (token); |
647 | json_decref (token_str); | 779 | json_decref (token_str); |
@@ -1038,22 +1170,196 @@ process_lookup_result (void *cls, uint32_t rd_count, | |||
1038 | json_decref (root); | 1170 | json_decref (root); |
1039 | } | 1171 | } |
1040 | 1172 | ||
1173 | |||
1174 | /** | ||
1175 | * Decrypts metainfo part from a token code | ||
1176 | */ | ||
1177 | static int | ||
1178 | decrypt_meta_str (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, | ||
1179 | const struct GNUNET_CRYPTO_EcdhePublicKey *ecdh_key, | ||
1180 | const char *enc_meta, | ||
1181 | size_t enc_meta_len, | ||
1182 | struct GNUNET_CRYPTO_EcdsaSignature *signature, | ||
1183 | char **meta_str) | ||
1184 | { | ||
1185 | struct GNUNET_HashCode new_key_hash; | ||
1186 | struct GNUNET_CRYPTO_SymmetricSessionKey enc_key; | ||
1187 | struct GNUNET_CRYPTO_SymmetricInitializationVector enc_iv; | ||
1188 | |||
1189 | char *meta_str_buf = GNUNET_malloc (enc_meta_len); | ||
1190 | size_t meta_size; | ||
1191 | |||
1192 | //Calculate symmetric key from ecdh parameters | ||
1193 | GNUNET_assert (GNUNET_OK == GNUNET_CRYPTO_ecdsa_ecdh (priv_key, | ||
1194 | ecdh_key, | ||
1195 | &new_key_hash)); | ||
1196 | |||
1197 | create_sym_key_from_ecdh (&new_key_hash, | ||
1198 | &enc_key, | ||
1199 | &enc_iv); | ||
1200 | |||
1201 | meta_size = GNUNET_CRYPTO_symmetric_decrypt (enc_meta, | ||
1202 | enc_meta_len, | ||
1203 | &enc_key, | ||
1204 | &enc_iv, | ||
1205 | meta_str_buf); | ||
1206 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Decrypted bytes: %d Expected bytes: %d\n", meta_size, enc_meta_len); | ||
1207 | if (-1 == meta_size) | ||
1208 | { | ||
1209 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n"); | ||
1210 | return GNUNET_SYSERR; | ||
1211 | } | ||
1212 | *meta_str = GNUNET_malloc (meta_size+1); | ||
1213 | memcpy (*meta_str, meta_str_buf, meta_size); | ||
1214 | (*meta_str)[meta_size] = '\0'; | ||
1215 | GNUNET_free (meta_str_buf); | ||
1216 | return GNUNET_OK; | ||
1217 | |||
1218 | } | ||
1219 | |||
1220 | static int | ||
1221 | extract_values_from_token_code (const char *token_code, | ||
1222 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key, | ||
1223 | struct GNUNET_CRYPTO_EcdsaSignature *signature, | ||
1224 | struct GNUNET_CRYPTO_EcdhePublicKey *ecdhe_pkey, | ||
1225 | char **label, | ||
1226 | struct GNUNET_CRYPTO_EcdsaPublicKey *id_pkey) | ||
1227 | { | ||
1228 | const char* enc_meta_str; | ||
1229 | const char* ecdh_enc_str; | ||
1230 | const char* signature_enc_str; | ||
1231 | const char* label_str; | ||
1232 | const char* identity_key_str; | ||
1233 | |||
1234 | json_t *root; | ||
1235 | json_t *signature_json; | ||
1236 | json_t *ecdh_json; | ||
1237 | json_t *enc_meta_json; | ||
1238 | json_t *label_json; | ||
1239 | json_t *identity_json; | ||
1240 | json_error_t err_json; | ||
1241 | char* enc_meta; | ||
1242 | char* meta_str; | ||
1243 | char* token_code_decoded; | ||
1244 | size_t enc_meta_len; | ||
1245 | |||
1246 | GNUNET_STRINGS_base64_decode (token_code, strlen (token_code), &token_code_decoded); | ||
1247 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Token Code: %s\n", token_code_decoded); | ||
1248 | root = json_loads (token_code_decoded, JSON_DECODE_ANY, &err_json); | ||
1249 | if (!root) | ||
1250 | { | ||
1251 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1252 | "%s\n", err_json.text); | ||
1253 | return GNUNET_SYSERR; | ||
1254 | } | ||
1255 | |||
1256 | signature_json = json_object_get (root, "signature"); | ||
1257 | ecdh_json = json_object_get (root, "ecdh"); | ||
1258 | enc_meta_json = json_object_get (root, "meta"); | ||
1259 | |||
1260 | signature_enc_str = json_string_value (signature_json); | ||
1261 | ecdh_enc_str = json_string_value (ecdh_json); | ||
1262 | enc_meta_str = json_string_value (enc_meta_json); | ||
1263 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (ecdh_enc_str, | ||
1264 | strlen (ecdh_enc_str), | ||
1265 | ecdhe_pkey, | ||
1266 | sizeof (struct GNUNET_CRYPTO_EcdhePublicKey))) | ||
1267 | { | ||
1268 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH PKEY %s invalid in metadata\n", ecdh_enc_str); | ||
1269 | json_decref (root); | ||
1270 | return GNUNET_SYSERR; | ||
1271 | } | ||
1272 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using ECDH pubkey %s for metadata decryption\n", ecdh_enc_str); | ||
1273 | if (GNUNET_OK != GNUNET_STRINGS_string_to_data (signature_enc_str, | ||
1274 | strlen (signature_enc_str), | ||
1275 | signature, | ||
1276 | sizeof (struct GNUNET_CRYPTO_EcdsaSignature))) | ||
1277 | { | ||
1278 | json_decref (root); | ||
1279 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "ECDH signature invalid in metadata\n"); | ||
1280 | return GNUNET_SYSERR; | ||
1281 | } | ||
1282 | enc_meta_len = GNUNET_STRINGS_base64_decode (enc_meta_str, | ||
1283 | strlen (enc_meta_str), | ||
1284 | &enc_meta); | ||
1285 | |||
1286 | if (GNUNET_OK != decrypt_meta_str (priv_key, | ||
1287 | ecdhe_pkey, | ||
1288 | enc_meta, | ||
1289 | enc_meta_len, | ||
1290 | signature, | ||
1291 | &meta_str)) | ||
1292 | { | ||
1293 | GNUNET_free (enc_meta); | ||
1294 | json_decref(root); | ||
1295 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata decryption failed\n"); | ||
1296 | return GNUNET_SYSERR; | ||
1297 | } | ||
1298 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Metadata: %s\n", meta_str); | ||
1299 | json_decref (root); | ||
1300 | root = json_loads (meta_str, JSON_DECODE_ANY, &err_json); | ||
1301 | if (!root) | ||
1302 | { | ||
1303 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1304 | "Error parsing metadata: %s\n", err_json.text); | ||
1305 | GNUNET_free (enc_meta); | ||
1306 | return GNUNET_SYSERR; | ||
1307 | } | ||
1308 | label_json = json_object_get (root, "label"); | ||
1309 | if (!json_is_string (label_json)) | ||
1310 | { | ||
1311 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1312 | "Error parsing metadata: %s\n", err_json.text); | ||
1313 | json_decref (root); | ||
1314 | GNUNET_free (enc_meta); | ||
1315 | return GNUNET_SYSERR; | ||
1316 | } | ||
1317 | |||
1318 | label_str = json_string_value (label_json); | ||
1319 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Found label: %s\n", label_str); | ||
1320 | GNUNET_asprintf (label, "%s", label_str); | ||
1321 | |||
1322 | identity_json = json_object_get (root, "identity"); | ||
1323 | if (!json_is_string (identity_json)) | ||
1324 | { | ||
1325 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | ||
1326 | "Error parsing metadata: %s\n", err_json.text); | ||
1327 | json_decref (root); | ||
1328 | GNUNET_free (enc_meta); | ||
1329 | return GNUNET_SYSERR; | ||
1330 | } | ||
1331 | identity_key_str = json_string_value (identity_json); | ||
1332 | GNUNET_STRINGS_string_to_data (identity_key_str, | ||
1333 | strlen (identity_key_str), | ||
1334 | id_pkey, | ||
1335 | sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); | ||
1336 | |||
1337 | GNUNET_free (enc_meta); | ||
1338 | json_decref (root); | ||
1339 | return GNUNET_OK; | ||
1340 | |||
1341 | } | ||
1342 | |||
1343 | |||
1041 | static void | 1344 | static void |
1042 | identity_master_cb (void *cls, | 1345 | exchange_token_code_cb (void *cls, |
1043 | struct GNUNET_IDENTITY_Ego *ego, | 1346 | struct GNUNET_IDENTITY_Ego *ego, |
1044 | void **ctx, | 1347 | void **ctx, |
1045 | const char *name) | 1348 | const char *name) |
1046 | { | 1349 | { |
1350 | const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv_key; | ||
1351 | |||
1047 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; | 1352 | struct GNUNET_CRYPTO_EcdsaPublicKey pkey; |
1353 | struct GNUNET_CRYPTO_EcdsaPublicKey pub_key; | ||
1354 | struct GNUNET_CRYPTO_EcdsaSignature sig; | ||
1355 | struct GNUNET_CRYPTO_EcdhePublicKey echde_pkey; | ||
1048 | struct RequestHandle *handle = cls; | 1356 | struct RequestHandle *handle = cls; |
1049 | struct GNUNET_HashCode key; | 1357 | struct GNUNET_HashCode key; |
1050 | json_t *root; | ||
1051 | json_t *pkey_json; | ||
1052 | json_error_t err_json; | ||
1053 | const char* pkey_str; | ||
1054 | char* code; | 1358 | char* code; |
1055 | char* code_decoded; | 1359 | char* code_decoded; |
1056 | char * lookup_query; | 1360 | char* lookup_query; |
1361 | char* label; | ||
1362 | char* pub_key_str; | ||
1057 | 1363 | ||
1058 | handle->op = NULL; | 1364 | handle->op = NULL; |
1059 | 1365 | ||
@@ -1064,8 +1370,8 @@ identity_master_cb (void *cls, | |||
1064 | return; | 1370 | return; |
1065 | } | 1371 | } |
1066 | 1372 | ||
1067 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_CODE, | 1373 | GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_IDENTITY_TOKEN_CODE, |
1068 | strlen (GNUNET_REST_JSONAPI_IDENTITY_OAUTH2_CODE), | 1374 | strlen (GNUNET_REST_JSONAPI_IDENTITY_TOKEN_CODE), |
1069 | &key); | 1375 | &key); |
1070 | 1376 | ||
1071 | if ( GNUNET_NO == | 1377 | if ( GNUNET_NO == |
@@ -1081,22 +1387,29 @@ identity_master_cb (void *cls, | |||
1081 | GNUNET_STRINGS_base64_decode (code, | 1387 | GNUNET_STRINGS_base64_decode (code, |
1082 | strlen (code), | 1388 | strlen (code), |
1083 | &code_decoded); | 1389 | &code_decoded); |
1084 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1390 | |
1085 | "%s\n", code_decoded); | 1391 | priv_key = GNUNET_IDENTITY_ego_get_private_key (ego); |
1086 | root = json_loads (code_decoded, JSON_DECODE_ANY, &err_json); | 1392 | GNUNET_IDENTITY_ego_get_public_key (ego, &pub_key); |
1087 | if (!root) | 1393 | pub_key_str = GNUNET_STRINGS_data_to_string_alloc (&pub_key, sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)); |
1394 | |||
1395 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Using private key corresponding to %s for ecdh\n", pub_key_str); | ||
1396 | |||
1397 | label = NULL; | ||
1398 | |||
1399 | if (GNUNET_SYSERR == extract_values_from_token_code (code, | ||
1400 | priv_key, | ||
1401 | &sig, | ||
1402 | &echde_pkey, | ||
1403 | &label, | ||
1404 | &pkey)) | ||
1088 | { | 1405 | { |
1089 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, | 1406 | handle->emsg = GNUNET_strdup ("Error extracting values from token code."); |
1090 | "%s\n", err_json.text); | 1407 | GNUNET_SCHEDULER_add_now (&do_error, handle); |
1408 | return; | ||
1091 | } | 1409 | } |
1092 | pkey_json = json_object_get (root, "identity"); | 1410 | GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Looking for token under %s\n", label); |
1093 | pkey_str = json_string_value (pkey_json); | ||
1094 | GNUNET_CRYPTO_ecdsa_public_key_from_string (pkey_str, | ||
1095 | strlen (pkey_str), | ||
1096 | &pkey); | ||
1097 | json_decref (root); | ||
1098 | handle->gns_handle = GNUNET_GNS_connect (cfg); | 1411 | handle->gns_handle = GNUNET_GNS_connect (cfg); |
1099 | GNUNET_asprintf (&lookup_query, "%s.gnu", code); | 1412 | GNUNET_asprintf (&lookup_query, "%s.gnu", label); |
1100 | 1413 | ||
1101 | handle->lookup_request = GNUNET_GNS_lookup (handle->gns_handle, | 1414 | handle->lookup_request = GNUNET_GNS_lookup (handle->gns_handle, |
1102 | lookup_query, | 1415 | lookup_query, |
@@ -1117,9 +1430,9 @@ identity_master_cb (void *cls, | |||
1117 | * @param cls the RequestHandle | 1430 | * @param cls the RequestHandle |
1118 | */ | 1431 | */ |
1119 | static void | 1432 | static void |
1120 | oauth_token_cont (struct RestConnectionDataHandle *con_handle, | 1433 | exchange_token_code_cont (struct RestConnectionDataHandle *con_handle, |
1121 | const char* url, | 1434 | const char* url, |
1122 | void *cls) | 1435 | void *cls) |
1123 | { | 1436 | { |
1124 | struct RequestHandle *handle = cls; | 1437 | struct RequestHandle *handle = cls; |
1125 | char* grant_type; | 1438 | char* grant_type; |
@@ -1141,9 +1454,11 @@ oauth_token_cont (struct RestConnectionDataHandle *con_handle, | |||
1141 | //Get token from GNS | 1454 | //Get token from GNS |
1142 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, | 1455 | handle->op = GNUNET_IDENTITY_get (handle->identity_handle, |
1143 | "gns-master", | 1456 | "gns-master", |
1144 | &identity_master_cb, | 1457 | &exchange_token_code_cb, |
1145 | handle); | 1458 | handle); |
1146 | } | 1459 | } |
1460 | |||
1461 | //TODO fail here | ||
1147 | } | 1462 | } |
1148 | 1463 | ||
1149 | /** | 1464 | /** |
@@ -1184,7 +1499,7 @@ init_cont (struct RequestHandle *handle) | |||
1184 | //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, | 1499 | //{MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_TOKEN_CHECK, &check_token_cont}, |
1185 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN, &list_token_cont}, | 1500 | {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_IDENTITY_TOKEN, &list_token_cont}, |
1186 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_TOKEN, &options_cont}, | 1501 | {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_IDENTITY_TOKEN, &options_cont}, |
1187 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &oauth_token_cont}, | 1502 | {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_IDENTITY_OAUTH2_TOKEN, &exchange_token_code_cont}, |
1188 | GNUNET_REST_HANDLER_END | 1503 | GNUNET_REST_HANDLER_END |
1189 | }; | 1504 | }; |
1190 | 1505 | ||
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h index 33ad1af2b..2ec3b4d8d 100644 --- a/src/include/gnunet_crypto_lib.h +++ b/src/include/gnunet_crypto_lib.h | |||
@@ -1498,6 +1498,21 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, | |||
1498 | const struct GNUNET_CRYPTO_EcdhePublicKey *pub, | 1498 | const struct GNUNET_CRYPTO_EcdhePublicKey *pub, |
1499 | struct GNUNET_HashCode *key_material); | 1499 | struct GNUNET_HashCode *key_material); |
1500 | 1500 | ||
1501 | /** | ||
1502 | * @ingroup crypto | ||
1503 | * Derive key material from a ECDH public key and a private ECDSA key. | ||
1504 | * Dual to #GNUNET_CRRYPTO_ecdh_ecdsa. | ||
1505 | * | ||
1506 | * @param priv private key from ECDSA to use for the ECDH (x) | ||
1507 | * @param pub public key to use for the ECDH (yG) | ||
1508 | * @param key_material where to write the key material H(h(x)yG) | ||
1509 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
1510 | */ | ||
1511 | int | ||
1512 | GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | ||
1513 | const struct GNUNET_CRYPTO_EcdhePublicKey *pub, | ||
1514 | struct GNUNET_HashCode *key_material); | ||
1515 | |||
1501 | 1516 | ||
1502 | /** | 1517 | /** |
1503 | * @ingroup crypto | 1518 | * @ingroup crypto |
@@ -1514,6 +1529,21 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | |||
1514 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub, | 1529 | const struct GNUNET_CRYPTO_EddsaPublicKey *pub, |
1515 | struct GNUNET_HashCode *key_material); | 1530 | struct GNUNET_HashCode *key_material); |
1516 | 1531 | ||
1532 | /** | ||
1533 | * @ingroup crypto | ||
1534 | * Derive key material from a EcDSA public key and a private ECDH key. | ||
1535 | * Dual to #GNUNET_CRRYPTO_ecdsa_ecdh. | ||
1536 | * | ||
1537 | * @param priv private key to use for the ECDH (y) | ||
1538 | * @param pub public key from ECDSA to use for the ECDH (X=h(x)G) | ||
1539 | * @param key_material where to write the key material H(yX)=H(h(x)yG) | ||
1540 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
1541 | */ | ||
1542 | int | ||
1543 | GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | ||
1544 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, | ||
1545 | struct GNUNET_HashCode *key_material); | ||
1546 | |||
1517 | 1547 | ||
1518 | /** | 1548 | /** |
1519 | * @ingroup crypto | 1549 | * @ingroup crypto |
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h index e9d5d05ed..dd6afbec5 100644 --- a/src/include/gnunet_signatures.h +++ b/src/include/gnunet_signatures.h | |||
@@ -181,7 +181,10 @@ extern "C" | |||
181 | */ | 181 | */ |
182 | #define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN 26 | 182 | #define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN 26 |
183 | 183 | ||
184 | 184 | /** | |
185 | * Signature for a GNUid Token Reference | ||
186 | */ | ||
187 | #define GNUNET_SIGNATURE_PURPOSE_GNUID_TOKEN_CODE 27 | ||
185 | 188 | ||
186 | #if 0 /* keep Emacsens' auto-indent happy */ | 189 | #if 0 /* keep Emacsens' auto-indent happy */ |
187 | { | 190 | { |
diff --git a/src/util/crypto_ecc.c b/src/util/crypto_ecc.c index bcc04fea5..c4e101369 100644 --- a/src/util/crypto_ecc.c +++ b/src/util/crypto_ecc.c | |||
@@ -1298,6 +1298,77 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv, | |||
1298 | return GNUNET_OK; | 1298 | return GNUNET_OK; |
1299 | } | 1299 | } |
1300 | 1300 | ||
1301 | /** | ||
1302 | * @ingroup crypto | ||
1303 | * Derive key material from a ECDH public key and a private ECDSA key. | ||
1304 | * Dual to #GNUNET_CRRYPTO_ecdh_eddsa. | ||
1305 | * | ||
1306 | * @param priv private key from ECDSA to use for the ECDH (x) | ||
1307 | * @param pub public key to use for the ECDH (yG) | ||
1308 | * @param key_material where to write the key material H(h(x)yG) | ||
1309 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
1310 | */ | ||
1311 | int | ||
1312 | GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv, | ||
1313 | const struct GNUNET_CRYPTO_EcdhePublicKey *pub, | ||
1314 | struct GNUNET_HashCode *key_material) | ||
1315 | { | ||
1316 | gcry_mpi_point_t result; | ||
1317 | gcry_mpi_point_t q; | ||
1318 | gcry_mpi_t d; | ||
1319 | gcry_ctx_t ctx; | ||
1320 | gcry_sexp_t pub_sexpr; | ||
1321 | gcry_mpi_t result_x; | ||
1322 | unsigned char xbuf[256 / 8]; | ||
1323 | size_t rsize; | ||
1324 | |||
1325 | /* first, extract the q = dP value from the public key */ | ||
1326 | if (0 != gcry_sexp_build (&pub_sexpr, NULL, | ||
1327 | "(public-key(ecc(curve " CURVE ")(q %b)))", | ||
1328 | (int)sizeof (pub->q_y), pub->q_y)) | ||
1329 | return GNUNET_SYSERR; | ||
1330 | GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, pub_sexpr, NULL)); | ||
1331 | gcry_sexp_release (pub_sexpr); | ||
1332 | q = gcry_mpi_ec_get_point ("q", ctx, 0); | ||
1333 | |||
1334 | /* second, extract the d value from our private key */ | ||
1335 | GNUNET_CRYPTO_mpi_scan_unsigned (&d, priv->d, sizeof (priv->d)); | ||
1336 | |||
1337 | /* then call the 'multiply' function, to compute the product */ | ||
1338 | result = gcry_mpi_point_new (0); | ||
1339 | gcry_mpi_ec_mul (result, d, q, ctx); | ||
1340 | gcry_mpi_point_release (q); | ||
1341 | gcry_mpi_release (d); | ||
1342 | |||
1343 | /* finally, convert point to string for hashing */ | ||
1344 | result_x = gcry_mpi_new (256); | ||
1345 | if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx)) | ||
1346 | { | ||
1347 | LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0); | ||
1348 | gcry_mpi_point_release (result); | ||
1349 | gcry_ctx_release (ctx); | ||
1350 | return GNUNET_SYSERR; | ||
1351 | } | ||
1352 | gcry_mpi_point_release (result); | ||
1353 | gcry_ctx_release (ctx); | ||
1354 | |||
1355 | rsize = sizeof (xbuf); | ||
1356 | GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE)); | ||
1357 | /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned' | ||
1358 | as that does not include the sign bit; x should be a 255-bit | ||
1359 | value, so with the sign it should fit snugly into the 256-bit | ||
1360 | xbuf */ | ||
1361 | GNUNET_assert (0 == | ||
1362 | gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize, | ||
1363 | result_x)); | ||
1364 | GNUNET_CRYPTO_hash (xbuf, | ||
1365 | rsize, | ||
1366 | key_material); | ||
1367 | gcry_mpi_release (result_x); | ||
1368 | return GNUNET_OK; | ||
1369 | } | ||
1370 | |||
1371 | |||
1301 | 1372 | ||
1302 | /** | 1373 | /** |
1303 | * @ingroup crypto | 1374 | * @ingroup crypto |
@@ -1369,6 +1440,24 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | |||
1369 | return GNUNET_OK; | 1440 | return GNUNET_OK; |
1370 | } | 1441 | } |
1371 | 1442 | ||
1372 | 1443 | /** | |
1444 | * @ingroup crypto | ||
1445 | * Derive key material from a ECDSA public key and a private ECDH key. | ||
1446 | * Dual to #GNUNET_CRRYPTO_eddsa_ecdh. | ||
1447 | * | ||
1448 | * @param priv private key to use for the ECDH (y) | ||
1449 | * @param pub public key from ECDSA to use for the ECDH (X=h(x)G) | ||
1450 | * @param key_material where to write the key material H(yX)=H(h(x)yG) | ||
1451 | * @return #GNUNET_SYSERR on error, #GNUNET_OK on success | ||
1452 | */ | ||
1453 | int | ||
1454 | GNUNET_CRYPTO_ecdh_ecdsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv, | ||
1455 | const struct GNUNET_CRYPTO_EcdsaPublicKey *pub, | ||
1456 | struct GNUNET_HashCode *key_material) | ||
1457 | { | ||
1458 | return GNUNET_CRYPTO_ecdh_eddsa (priv, | ||
1459 | (const struct GNUNET_CRYPTO_EddsaPublicKey *)pub, | ||
1460 | key_material); | ||
1461 | } | ||
1373 | 1462 | ||
1374 | /* end of crypto_ecc.c */ | 1463 | /* end of crypto_ecc.c */ |