/** * Decrypt data with the axolotl tunnel key. * * @param t Tunnel whose key to use. * @param dst Destination for the decrypted data, must contain @a size bytes. * @param src Source of the ciphertext. Can overlap with @c dst, must contain @a size bytes. * @param size Size of the @a src and @a dst buffers */ static void t_ax_decrypt (struct CadetTunnel *t, void *dst, const void *src, size_t size) { struct GNUNET_CRYPTO_SymmetricSessionKey MK; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct CadetTunnelAxolotl *ax; size_t out_size; ax = &t->ax; t_hmac_derive_key (&ax->CKr, &MK, "0", 1); GNUNET_CRYPTO_symmetric_derive_iv (&iv, &MK, NULL, 0, NULL); GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader)); out_size = GNUNET_CRYPTO_symmetric_decrypt (src, size, &MK, &iv, dst); GNUNET_assert (out_size == size); t_hmac_derive_key (&ax->CKr, &ax->CKr, "1", 1); }
static void perfEncrypt () { unsigned int i; char buf[64 * 1024]; char rbuf[64 * 1024]; struct GNUNET_CRYPTO_SymmetricSessionKey sk; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; GNUNET_CRYPTO_symmetric_create_session_key (&sk); memset (buf, 1, sizeof (buf)); for (i = 0; i < 1024; i++) { memset (&iv, (int8_t) i, sizeof (iv)); GNUNET_CRYPTO_symmetric_encrypt (buf, sizeof (buf), &sk, &iv, rbuf); GNUNET_CRYPTO_symmetric_decrypt (rbuf, sizeof (buf), &sk, &iv, buf); } memset (rbuf, 1, sizeof (rbuf)); GNUNET_assert (0 == memcmp (rbuf, buf, sizeof (buf))); }
/** * Decrypt the given UBlock, storing the result in output. * * @param input input data * @param input_len number of bytes in @a input * @param ns public key under which the UBlock was stored * @param label label under which the UBlock was stored * @param output where to write the result, has input_len bytes */ void GNUNET_FS_ublock_decrypt_ (const void *input, size_t input_len, const struct GNUNET_CRYPTO_EcdsaPublicKey *ns, const char *label, void *output) { struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; derive_ublock_encryption_key (&skey, &iv, label, ns); GNUNET_CRYPTO_symmetric_decrypt (input, input_len, &skey, &iv, output); }
/** * Decrypt header with the current axolotl header key. * * @param t Tunnel whose current ax HK to use. * @param src Message whose header to decrypt. * @param dst Where to decrypt header to. */ static void t_h_decrypt (struct CadetTunnel *t, const struct GNUNET_CADET_Encrypted *src, struct GNUNET_CADET_Encrypted *dst) { struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct CadetTunnelAxolotl *ax; size_t out_size; ax = &t->ax; GNUNET_CRYPTO_symmetric_derive_iv (&iv, &ax->HKr, NULL, 0, NULL); out_size = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE, &ax->HKr, &iv, &dst->Ns); GNUNET_assert (AX_HEADER_SIZE == out_size); }
static int testSymcipher () { struct GNUNET_CRYPTO_SymmetricSessionKey key; char result[100]; int size; char res[100]; GNUNET_CRYPTO_symmetric_create_session_key (&key); size = GNUNET_CRYPTO_symmetric_encrypt (TESTSTRING, strlen (TESTSTRING) + 1, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) INITVALUE, result); if (size == -1) { printf ("symciphertest failed: encryptBlock returned %d\n", size); return 1; } size = GNUNET_CRYPTO_symmetric_decrypt (result, size, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) INITVALUE, res); if (strlen (TESTSTRING) + 1 != size) { printf ("symciphertest failed: decryptBlock returned %d\n", size); return 1; } if (0 != strcmp (res, TESTSTRING)) { printf ("symciphertest failed: %s != %s\n", res, TESTSTRING); return 1; } else return 0; }
/** * Decrypt and verify data with the appropriate tunnel key and verify that the * data has not been altered since it was sent by the remote peer. * * @param t Tunnel whose key to use. * @param dst Destination for the plaintext. * @param src Source of the message. Can overlap with @c dst. * @param size Size of the message. * @return Size of the decrypted data, -1 if an error was encountered. */ static ssize_t try_old_ax_keys (struct CadetTunnel *t, void *dst, const struct GNUNET_CADET_Encrypted *src, size_t size) { struct CadetTunnelSkippedKey *key; struct GNUNET_ShortHashCode *hmac; struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CADET_Encrypted plaintext_header; struct GNUNET_CRYPTO_SymmetricSessionKey *valid_HK; size_t esize; size_t res; size_t len; unsigned int N; LOG (GNUNET_ERROR_TYPE_DEBUG, "Trying skipped keys\n"); hmac = &plaintext_header.hmac; esize = size - sizeof (struct GNUNET_CADET_Encrypted); /* Find a correct Header Key */ valid_HK = NULL; for (key = t->ax.skipped_head; NULL != key; key = key->next) { t_hmac (&src->Ns, AX_HEADER_SIZE + esize, 0, &key->HK, hmac); if (0 == memcmp (hmac, &src->hmac, sizeof (*hmac))) { valid_HK = &key->HK; break; } } if (NULL == key) return -1; /* Should've been checked in -cadet_connection.c handle_cadet_encrypted. */ GNUNET_assert (size > sizeof (struct GNUNET_CADET_Encrypted)); len = size - sizeof (struct GNUNET_CADET_Encrypted); GNUNET_assert (len >= sizeof (struct GNUNET_MessageHeader)); /* Decrypt header */ GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->HK, NULL, 0, NULL); res = GNUNET_CRYPTO_symmetric_decrypt (&src->Ns, AX_HEADER_SIZE, &key->HK, &iv, &plaintext_header.Ns); GNUNET_assert (AX_HEADER_SIZE == res); /* Find the correct message key */ N = ntohl (plaintext_header.Ns); while ( (NULL != key) && (N != key->Kn) ) key = key->next; if ( (NULL == key) || (0 != memcmp (&key->HK, valid_HK, sizeof (*valid_HK))) ) return -1; /* Decrypt payload */ GNUNET_CRYPTO_symmetric_derive_iv (&iv, &key->MK, NULL, 0, NULL); res = GNUNET_CRYPTO_symmetric_decrypt (&src[1], len, &key->MK, &iv, dst); delete_skipped_key (t, key); return res; }
/** * Decrypt block. * * @param block block to decrypt * @param zone_key public key of the zone * @param label the name for the records * @param proc function to call with the result * @param proc_cls closure for proc * @return #GNUNET_OK on success, #GNUNET_SYSERR if the block was * not well-formed */ int GNUNET_GNSRECORD_block_decrypt (const struct GNUNET_GNSRECORD_Block *block, const struct GNUNET_CRYPTO_EcdsaPublicKey *zone_key, const char *label, GNUNET_GNSRECORD_RecordCallback proc, void *proc_cls) { size_t payload_len = ntohl (block->purpose.size) - sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) - sizeof (struct GNUNET_TIME_AbsoluteNBO); struct GNUNET_CRYPTO_SymmetricInitializationVector iv; struct GNUNET_CRYPTO_SymmetricSessionKey skey; if (ntohl (block->purpose.size) < sizeof (struct GNUNET_CRYPTO_EccSignaturePurpose) + sizeof (struct GNUNET_TIME_AbsoluteNBO)) { GNUNET_break_op (0); return GNUNET_SYSERR; } derive_block_aes_key (&iv, &skey, label, zone_key); { char payload[payload_len]; uint32_t rd_count; GNUNET_break (payload_len == GNUNET_CRYPTO_symmetric_decrypt (&block[1], payload_len, &skey, &iv, payload)); memcpy (&rd_count, payload, sizeof (uint32_t)); rd_count = ntohl (rd_count); if (rd_count > 2048) { /* limit to sane value */ GNUNET_break_op (0); return GNUNET_SYSERR; } { struct GNUNET_GNSRECORD_Data rd[rd_count]; unsigned int i; unsigned int j; unsigned int k; struct GNUNET_TIME_Absolute now; if (GNUNET_OK != GNUNET_GNSRECORD_records_deserialize (payload_len - sizeof (uint32_t), &payload[sizeof (uint32_t)], rd_count, rd)) { GNUNET_break_op (0); return GNUNET_SYSERR; } /* hide expired records */ now = GNUNET_TIME_absolute_get (); j = 0; for (i=0;i<rd_count;i++) { if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION)) { /* encrypted blocks must never have relative expiration times, skip! */ GNUNET_break_op (0); continue; } if (0 != (rd[i].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD)) { int include_record = GNUNET_YES; /* Shadow record, figure out if we have a not expired active record */ for (k=0;k<rd_count;k++) { if (k == i) continue; if (rd[i].expiration_time < now.abs_value_us) include_record = GNUNET_NO; /* Shadow record is expired */ if ((rd[k].record_type == rd[i].record_type) && (rd[k].expiration_time >= now.abs_value_us) && (0 == (rd[k].flags & GNUNET_GNSRECORD_RF_SHADOW_RECORD))) include_record = GNUNET_NO; /* We have a non-expired, non-shadow record of the same type */ } if (GNUNET_YES == include_record) { rd[i].flags ^= GNUNET_GNSRECORD_RF_SHADOW_RECORD; /* Remove Flag */ if (j != i) rd[j] = rd[i]; j++; } } else if (rd[i].expiration_time >= now.abs_value_us) { /* Include this record */ if (j != i) rd[j] = rd[i]; j++; } } rd_count = j; if (NULL != proc) proc (proc_cls, rd_count, (0 != rd_count) ? rd : NULL); } } return GNUNET_OK; }
static int verifyCrypto () { struct GNUNET_CRYPTO_SymmetricSessionKey key; char result[GNUNET_CRYPTO_AES_KEY_LENGTH]; char *res; int ret; unsigned char plain[] = { 29, 128, 192, 253, 74, 171, 38, 187, 84, 219, 76, 76, 209, 118, 33, 249, 172, 124, 96, 9, 157, 110, 8, 215, 200, 63, 69, 230, 157, 104, 247, 164 }; unsigned char raw_key_aes[] = { 106, 74, 209, 88, 145, 55, 189, 135, 125, 180, 225, 108, 183, 54, 25, 169, 129, 188, 131, 75, 227, 245, 105, 10, 225, 15, 115, 159, 148, 184, 34, 191 }; unsigned char raw_key_twofish[] = { 145, 55, 189, 135, 125, 180, 225, 108, 183, 54, 25, 169, 129, 188, 131, 75, 227, 245, 105, 10, 225, 15, 115, 159, 148, 184, 34, 191, 106, 74, 209, 88 }; unsigned char encrresult[] = { 155, 88, 106, 174, 124, 172, 47, 149, 85, 15, 208, 176, 65, 124, 155, 74, 215, 25, 177, 231, 162, 109, 165, 4, 133, 165, 93, 44, 213, 77, 206, 204, 1 }; res = NULL; ret = 0; memcpy (key.aes_key, raw_key_aes, GNUNET_CRYPTO_AES_KEY_LENGTH); memcpy (key.twofish_key, raw_key_twofish, GNUNET_CRYPTO_AES_KEY_LENGTH); if (GNUNET_CRYPTO_AES_KEY_LENGTH != GNUNET_CRYPTO_symmetric_encrypt (plain, GNUNET_CRYPTO_AES_KEY_LENGTH, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) "testtesttesttesttesttesttesttest", result)) { printf ("Wrong return value from encrypt block.\n"); ret = 1; goto error; } if (0 != memcmp (encrresult, result, GNUNET_CRYPTO_AES_KEY_LENGTH)) { int i; printf ("Encrypted result wrong.\n"); for (i=0; i<GNUNET_CRYPTO_AES_KEY_LENGTH; i++) printf ("%u, ", (uint8_t) result[i]); ret = 1; goto error; } res = GNUNET_malloc (GNUNET_CRYPTO_AES_KEY_LENGTH); if (GNUNET_CRYPTO_AES_KEY_LENGTH != GNUNET_CRYPTO_symmetric_decrypt (result, GNUNET_CRYPTO_AES_KEY_LENGTH, &key, (const struct GNUNET_CRYPTO_SymmetricInitializationVector *) "testtesttesttesttesttesttesttest", res)) { printf ("Wrong return value from decrypt block.\n"); ret = 1; goto error; } if (0 != memcmp (res, plain, GNUNET_CRYPTO_AES_KEY_LENGTH)) { printf ("Decrypted result does not match input.\n"); ret = 1; } error: GNUNET_free_non_null (res); return ret; }