2 * Helper functions for libgcrypt
3 * By Erik de Jong <erikdejong@gmail.com>
4 * Copyright 2017 Erik de Jong
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * SPDX-License-Identifier: GPL-2.0-or-later
15 gcry_error_t
ws_hmac_buffer(int algo
, void *digest
, const void *buffer
, size_t length
, const void *key
, size_t keylen
)
17 gcry_md_hd_t hmac_handle
;
18 gcry_error_t result
= gcry_md_open(&hmac_handle
, algo
, GCRY_MD_FLAG_HMAC
);
22 result
= gcry_md_setkey(hmac_handle
, key
, keylen
);
24 gcry_md_close(hmac_handle
);
27 gcry_md_write(hmac_handle
, buffer
, length
);
28 memcpy(digest
, gcry_md_read(hmac_handle
, 0), gcry_md_get_algo_dlen(algo
));
29 gcry_md_close(hmac_handle
);
30 return GPG_ERR_NO_ERROR
;
33 gcry_error_t
ws_cmac_buffer(int algo
, void *digest
, const void *buffer
, size_t length
, const void *key
, size_t keylen
)
35 gcry_mac_hd_t cmac_handle
;
36 gcry_error_t result
= gcry_mac_open(&cmac_handle
, algo
, 0, NULL
);
40 result
= gcry_mac_setkey(cmac_handle
, key
, keylen
);
42 gcry_mac_close(cmac_handle
);
45 gcry_mac_write(cmac_handle
, buffer
, length
);
46 result
= gcry_mac_read(cmac_handle
, digest
, &keylen
);
47 gcry_mac_close(cmac_handle
);
51 void crypt_des_ecb(uint8_t *output
, const uint8_t *buffer
, const uint8_t *key56
)
54 gcry_cipher_hd_t handle
;
56 memset(output
, 0x00, 8);
58 /* Transform 56 bits key into 64 bits DES key */
60 key64
[1] = (key56
[0] << 7) | (key56
[1] >> 1);
61 key64
[2] = (key56
[1] << 6) | (key56
[2] >> 2);
62 key64
[3] = (key56
[2] << 5) | (key56
[3] >> 3);
63 key64
[4] = (key56
[3] << 4) | (key56
[4] >> 4);
64 key64
[5] = (key56
[4] << 3) | (key56
[5] >> 5);
65 key64
[6] = (key56
[5] << 2) | (key56
[6] >> 6);
66 key64
[7] = (key56
[6] << 1);
68 if (gcry_cipher_open(&handle
, GCRY_CIPHER_DES
, GCRY_CIPHER_MODE_ECB
, 0)) {
71 if (gcry_cipher_setkey(handle
, key64
, 8)) {
72 gcry_cipher_close(handle
);
75 gcry_cipher_encrypt(handle
, output
, 8, buffer
, 8);
76 gcry_cipher_close(handle
);
79 void decrypt_des_ecb(uint8_t *output
, const uint8_t *buffer
, const uint8_t *key56
)
82 gcry_cipher_hd_t handle
;
84 memset(output
, 0x00, 8);
86 /* Transform 56 bits key into 64 bits DES key */
88 key64
[1] = (key56
[0] << 7) | (key56
[1] >> 1);
89 key64
[2] = (key56
[1] << 6) | (key56
[2] >> 2);
90 key64
[3] = (key56
[2] << 5) | (key56
[3] >> 3);
91 key64
[4] = (key56
[3] << 4) | (key56
[4] >> 4);
92 key64
[5] = (key56
[4] << 3) | (key56
[5] >> 5);
93 key64
[6] = (key56
[5] << 2) | (key56
[6] >> 6);
94 key64
[7] = (key56
[6] << 1);
96 if (gcry_cipher_open(&handle
, GCRY_CIPHER_DES
, GCRY_CIPHER_MODE_ECB
, 0)) {
99 if (gcry_cipher_setkey(handle
, key64
, 8)) {
100 gcry_cipher_close(handle
);
103 gcry_cipher_decrypt(handle
, output
, 8, buffer
, 8);
104 gcry_cipher_close(handle
);
107 size_t rsa_decrypt_inplace(const unsigned len
, unsigned char* data
, gcry_sexp_t pk
, bool pkcs1_padding
, char **err
)
110 size_t decr_len
= 0, i
= 0;
111 gcry_sexp_t s_data
= NULL
, s_plain
= NULL
;
112 gcry_mpi_t encr_mpi
= NULL
, text
= NULL
;
116 /* create mpi representation of encrypted data */
117 rc
= gcry_mpi_scan(&encr_mpi
, GCRYMPI_FMT_USG
, data
, len
, NULL
);
119 *err
= ws_strdup_printf("can't convert data to mpi (size %d):%s", len
, gcry_strerror(rc
));
123 /* put the data into a simple list */
124 rc
= gcry_sexp_build(&s_data
, NULL
, "(enc-val(rsa(a%m)))", encr_mpi
);
126 *err
= ws_strdup_printf("can't build encr_sexp:%s", gcry_strerror(rc
));
131 /* pass it to libgcrypt */
132 rc
= gcry_pk_decrypt(&s_plain
, s_data
, pk
);
135 *err
= ws_strdup_printf("can't decrypt key:%s", gcry_strerror(rc
));
140 /* convert plain text sexp to mpi format */
141 text
= gcry_sexp_nth_mpi(s_plain
, 0, 0);
143 *err
= g_strdup("can't convert sexp to mpi");
148 /* compute size requested for plaintext buffer */
149 rc
= gcry_mpi_print(GCRYMPI_FMT_USG
, NULL
, 0, &decr_len
, text
);
151 *err
= ws_strdup_printf("can't compute decr size:%s", gcry_strerror(rc
));
156 /* sanity check on out buffer */
157 if (decr_len
> len
) {
158 *err
= ws_strdup_printf("decrypted data is too long ?!? (%zu max %d)", decr_len
, len
);
163 /* write plain text to newly allocated buffer */
164 rc
= gcry_mpi_print(GCRYMPI_FMT_USG
, data
, len
, &decr_len
, text
);
166 *err
= ws_strdup_printf("can't print decr data to mpi (size %zu):%s", decr_len
, gcry_strerror(rc
));
172 /* strip the padding*/
174 for (i
= 1; i
< decr_len
; i
++) {
182 memmove(data
, data
+rc
, decr_len
);
186 gcry_sexp_release(s_data
);
187 gcry_sexp_release(s_plain
);
188 gcry_mpi_release(encr_mpi
);
189 gcry_mpi_release(text
);
194 hkdf_expand(int hashalgo
, const uint8_t *prk
, unsigned prk_len
, const uint8_t *info
, unsigned info_len
,
195 uint8_t *out
, unsigned out_len
)
197 // Current maximum hash output size: 48 bytes for SHA-384.
198 unsigned char lastoutput
[48];
201 const unsigned hash_len
= gcry_md_get_algo_dlen(hashalgo
);
203 /* Some sanity checks */
204 if (!(out_len
> 0 && out_len
<= 255 * hash_len
) ||
205 !(hash_len
> 0 && hash_len
<= sizeof(lastoutput
))) {
206 return GPG_ERR_INV_ARG
;
209 err
= gcry_md_open(&h
, hashalgo
, GCRY_MD_FLAG_HMAC
);
214 for (unsigned offset
= 0; offset
< out_len
; offset
+= hash_len
) {
216 gcry_md_setkey(h
, prk
, prk_len
); /* Set PRK */
218 gcry_md_write(h
, lastoutput
, hash_len
); /* T(1..N) */
220 gcry_md_write(h
, info
, info_len
); /* info */
221 gcry_md_putc(h
, (uint8_t) (offset
/ hash_len
+ 1)); /* constant 0x01..N */
223 memcpy(lastoutput
, gcry_md_read(h
, hashalgo
), hash_len
);
224 memcpy(out
+ offset
, lastoutput
, MIN(hash_len
, out_len
- offset
));
232 hpke_extract(uint16_t kdf_id
, const uint8_t *salt
, unsigned salt_len
, const uint8_t *suite_id
, const char *label
,
233 const uint8_t *ikm
, unsigned ikm_len
, uint8_t *out
)
236 gcry_md_hd_t hmac_handle
;
238 case HPKE_HKDF_SHA256
:
239 hashalgo
= GCRY_MD_SHA256
;
241 case HPKE_HKDF_SHA384
:
242 hashalgo
= GCRY_MD_SHA384
;
244 case HPKE_HKDF_SHA512
:
245 hashalgo
= GCRY_MD_SHA512
;
248 return GPG_ERR_DIGEST_ALGO
;
250 gcry_error_t result
= gcry_md_open(&hmac_handle
, hashalgo
, GCRY_MD_FLAG_HMAC
);
254 result
= gcry_md_setkey(hmac_handle
, salt
, salt_len
);
256 gcry_md_close(hmac_handle
);
259 gcry_md_write(hmac_handle
, HPKE_VERSION_ID
, sizeof(HPKE_VERSION_ID
) - 1);
260 gcry_md_write(hmac_handle
, suite_id
, HPKE_SUIT_ID_LEN
);
261 gcry_md_write(hmac_handle
, label
, strlen(label
));
262 gcry_md_write(hmac_handle
, ikm
, ikm_len
);
263 memcpy(out
, gcry_md_read(hmac_handle
, 0), hpke_hkdf_len(kdf_id
));
264 gcry_md_close(hmac_handle
);
265 return GPG_ERR_NO_ERROR
;
269 hpke_hkdf_len(uint16_t kdf_id
)
272 case HPKE_HKDF_SHA256
:
273 return HASH_SHA2_256_LENGTH
;
274 case HPKE_HKDF_SHA384
:
275 return HASH_SHA2_384_LENGTH
;
276 case HPKE_HKDF_SHA512
:
277 return HASH_SHA2_512_LENGTH
;
284 hpke_aead_key_len(uint16_t aead_id
)
287 case HPKE_AEAD_AES_128_GCM
:
288 return AEAD_AES_128_GCM_KEY_LENGTH
;
289 case HPKE_AEAD_AES_256_GCM
:
290 return AEAD_AES_256_GCM_KEY_LENGTH
;
291 case HPKE_AEAD_CHACHA20POLY1305
:
292 return AEAD_CHACHA20POLY1305_KEY_LENGTH
;
299 hpke_aead_nonce_len(uint16_t aead_id
)
302 case HPKE_AEAD_AES_128_GCM
:
303 case HPKE_AEAD_AES_256_GCM
:
304 case HPKE_AEAD_CHACHA20POLY1305
:
305 return HPKE_AEAD_NONCE_LENGTH
;
312 hpke_suite_id(uint16_t kem_id
, uint16_t kdf_id
, uint16_t aead_id
, uint8_t *suite_id
)
315 memcpy(suite_id
, HPKE_SUIT_PREFIX
, sizeof(HPKE_SUIT_PREFIX
) - 1);
316 offset
+= sizeof(HPKE_SUIT_PREFIX
) - 1;
317 suite_id
[offset
++] = (kem_id
>> 8) & 0xFF;
318 suite_id
[offset
++] = kem_id
& 0xFF;
319 suite_id
[offset
++] = (kdf_id
>> 8) & 0xFF;
320 suite_id
[offset
++] = kdf_id
& 0xFF;
321 suite_id
[offset
++] = (aead_id
>> 8) & 0xFF;
322 suite_id
[offset
++] = aead_id
& 0xFF;
326 hpke_expand(uint16_t kdf_id
, const uint8_t *prk
, const uint8_t *suite_id
, const char *label
,
327 const uint8_t *info
, uint8_t *out
, uint16_t out_len
)
330 GByteArray
* labeled_info
= g_byte_array_new();
331 uint16_t out_len_be
= GUINT16_TO_BE(out_len
);
334 case HPKE_HKDF_SHA256
:
335 hashalgo
= GCRY_MD_SHA256
;
337 case HPKE_HKDF_SHA384
:
338 hashalgo
= GCRY_MD_SHA384
;
340 case HPKE_HKDF_SHA512
:
341 hashalgo
= GCRY_MD_SHA512
;
344 return GPG_ERR_DIGEST_ALGO
;
346 g_byte_array_append(labeled_info
, (uint8_t *)&out_len_be
, 2);
347 g_byte_array_append(labeled_info
, HPKE_VERSION_ID
, sizeof(HPKE_VERSION_ID
) - 1);
348 g_byte_array_append(labeled_info
, suite_id
, HPKE_SUIT_ID_LEN
);
349 g_byte_array_append(labeled_info
, label
, (unsigned)strlen(label
));
350 g_byte_array_append(labeled_info
, info
, (unsigned)(1 + hpke_hkdf_len(kdf_id
) * 2));
351 result
= hkdf_expand(hashalgo
, prk
, (unsigned)hpke_hkdf_len(kdf_id
), labeled_info
->data
, labeled_info
->len
, out
, out_len
);
352 g_byte_array_free(labeled_info
, TRUE
);
357 hpke_key_schedule(uint16_t kdf_id
, uint16_t aead_id
, const uint8_t *salt
, unsigned salt_len
, const uint8_t *suite_id
,
358 const uint8_t *ikm
, unsigned ikm_len
, uint8_t mode
, uint8_t *key
, uint8_t *base_nonce
)
360 uint8_t secret
[HPKE_MAX_KDF_LEN
];
361 uint8_t context
[HPKE_MAX_KDF_LEN
* 2 + 1];
362 size_t kdf_len
= hpke_hkdf_len(kdf_id
);
364 gcry_error_t result
= hpke_extract(kdf_id
, NULL
, 0, suite_id
, "psk_id_hash", NULL
, 0, context
+ 1);
368 result
= hpke_extract(kdf_id
, NULL
, 0, suite_id
, "info_hash", ikm
, ikm_len
, context
+ 1 + kdf_len
);
372 result
= hpke_extract(kdf_id
, salt
, salt_len
, suite_id
, "secret", NULL
, 0, secret
);
376 result
= hpke_expand(kdf_id
, secret
, suite_id
, "key", context
, key
, hpke_aead_key_len(aead_id
));
380 result
= hpke_expand(kdf_id
, secret
, suite_id
, "base_nonce", context
, base_nonce
, hpke_aead_nonce_len(aead_id
));
385 hpke_setup_aead(gcry_cipher_hd_t
* cipher
, uint16_t aead_id
, uint8_t *key
)
389 case HPKE_AEAD_AES_128_GCM
:
390 err
= gcry_cipher_open(cipher
, GCRY_CIPHER_AES128
, GCRY_CIPHER_MODE_GCM
, 0);
392 case HPKE_AEAD_AES_256_GCM
:
393 err
= gcry_cipher_open(cipher
, GCRY_CIPHER_AES256
, GCRY_CIPHER_MODE_GCM
, 0);
395 case HPKE_AEAD_CHACHA20POLY1305
:
396 err
= gcry_cipher_open(cipher
, GCRY_CIPHER_CHACHA20
, GCRY_CIPHER_MODE_POLY1305
, 0);
399 return GPG_ERR_CIPHER_ALGO
;
403 return gcry_cipher_setkey(*(cipher
), key
, hpke_aead_key_len(aead_id
));
407 hpke_set_nonce(gcry_cipher_hd_t cipher
, uint64_t seq
, uint8_t *base_nonce
, size_t nonce_len
)
410 uint8_t *nonce
= (uint8_t *)wmem_alloc0(NULL
, nonce_len
);
412 for (i
= 1; i
< 9; i
++) {
413 nonce
[nonce_len
- i
] = seq
& 255;
416 for (i
= 0; i
< nonce_len
; i
++) {
417 nonce
[i
] ^= base_nonce
[i
];
419 return gcry_cipher_setiv(cipher
, nonce
, nonce_len
);
423 * Editor modelines - https://www.wireshark.org/tools/modelines.html
428 * indent-tabs-mode: t
431 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
432 * :indentSize=8:tabSize=8:noTabs=false: