-
Notifications
You must be signed in to change notification settings - Fork 3k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement HKDF expand function based on RFC 8446
Use crypto_epoch.c/h for the new functions since they are linked to the epoch key usage in OpenVPN. Change-Id: I3a1c6561f4d9a69e2a441d49dff620b4258a1bcc Signed-off-by: Arne Schwabe <[email protected]> Acked-by: MaxF <[email protected]> Acked-by: Gert Doering <[email protected]> Message-Id: <[email protected]> URL: https://www.mail-archive.com/[email protected]/msg30149.html Signed-off-by: Gert Doering <[email protected]>
- Loading branch information
Showing
7 changed files
with
434 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
/* | ||
* OpenVPN -- An application to securely tunnel IP networks | ||
* over a single TCP/UDP port, with support for SSL/TLS-based | ||
* session authentication and key exchange, | ||
* packet encryption, packet authentication, and | ||
* packet compression. | ||
* | ||
* Copyright (C) 2024 OpenVPN Inc <[email protected]> | ||
* Copyright (C) 2024 Arne Schwabe <[email protected]> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 | ||
* as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License along | ||
* with this program; if not, write to the Free Software Foundation, Inc., | ||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
*/ | ||
|
||
|
||
#ifdef HAVE_CONFIG_H | ||
#include "config.h" | ||
#endif | ||
|
||
#include <inttypes.h> | ||
#include "crypto_backend.h" | ||
#include "buffer.h" | ||
#include "integer.h" | ||
|
||
void | ||
ovpn_hkdf_expand(const uint8_t *secret, | ||
const uint8_t *info, int info_len, | ||
uint8_t *out, int out_len) | ||
{ | ||
hmac_ctx_t *hmac_ctx = hmac_ctx_new(); | ||
hmac_ctx_init(hmac_ctx, secret, "SHA256"); | ||
|
||
const int digest_size = SHA256_DIGEST_LENGTH; | ||
|
||
/* T(0) = empty string */ | ||
uint8_t t_prev[SHA256_DIGEST_LENGTH]; | ||
int t_prev_len = 0; | ||
|
||
for (uint8_t block = 1; (block - 1) * digest_size < out_len; block++) | ||
{ | ||
hmac_ctx_reset(hmac_ctx); | ||
|
||
/* calculate T(block) */ | ||
hmac_ctx_update(hmac_ctx, t_prev, t_prev_len); | ||
hmac_ctx_update(hmac_ctx, info, info_len); | ||
hmac_ctx_update(hmac_ctx, &block, 1); | ||
hmac_ctx_final(hmac_ctx, t_prev); | ||
t_prev_len = digest_size; | ||
|
||
/* Copy a full hmac output or remaining bytes */ | ||
int out_offset = (block - 1) * digest_size; | ||
int copylen = min_int(digest_size, out_len - out_offset); | ||
|
||
memcpy(out + out_offset, t_prev, copylen); | ||
} | ||
hmac_ctx_cleanup(hmac_ctx); | ||
hmac_ctx_free(hmac_ctx); | ||
} | ||
|
||
bool | ||
ovpn_expand_label(const uint8_t *secret, size_t secret_len, | ||
const uint8_t *label, size_t label_len, | ||
const uint8_t *context, size_t context_len, | ||
uint8_t *out, uint16_t out_len) | ||
{ | ||
if (secret_len != 32 || label_len > 250 || context_len > 255 | ||
|| label_len < 1) | ||
{ | ||
/* Our current implementation is not a general purpose one | ||
* and assumes that the secret size matches the size of the | ||
* hash (SHA256) key. Also label length and context length | ||
* need need to be in range */ | ||
return false; | ||
} | ||
|
||
struct gc_arena gc = gc_new(); | ||
/* 2 byte for the outlen encoded as uint16, 5 bytes for "ovpn ", | ||
* 1 byte for context len byte and 1 byte for label len byte */ | ||
const uint8_t *label_prefix = (const uint8_t *) ("ovpn "); | ||
int prefix_len = 5; | ||
|
||
int hkdf_label_len = 2 + prefix_len + 1 + label_len + 1 + context_len; | ||
struct buffer hkdf_label = alloc_buf_gc(hkdf_label_len, &gc); | ||
|
||
buf_write_u16(&hkdf_label, out_len); | ||
buf_write_u8(&hkdf_label, prefix_len + label_len); | ||
buf_write(&hkdf_label, label_prefix, prefix_len); | ||
buf_write(&hkdf_label, label, label_len); | ||
|
||
buf_write_u8(&hkdf_label, context_len); | ||
if (context_len > 0) | ||
{ | ||
buf_write(&hkdf_label, context, context_len); | ||
} | ||
|
||
ASSERT(buf_len(&hkdf_label) == hkdf_label_len); | ||
|
||
ovpn_hkdf_expand(secret, buf_bptr(&hkdf_label), | ||
buf_len(&hkdf_label), out, out_len); | ||
|
||
gc_free(&gc); | ||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* OpenVPN -- An application to securely tunnel IP networks | ||
* over a single TCP/UDP port, with support for SSL/TLS-based | ||
* session authentication and key exchange, | ||
* packet encryption, packet authentication, and | ||
* packet compression. | ||
* | ||
* Copyright (C) 2024 OpenVPN Inc <[email protected]> | ||
* Copyright (C) 2024 Arne Schwabe <[email protected]> | ||
* | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU General Public License version 2 | ||
* as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU General Public License along | ||
* with this program; if not, write to the Free Software Foundation, Inc., | ||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
*/ | ||
|
||
#ifndef CRYPTO_EPOCH_H | ||
#define CRYPTO_EPOCH_H | ||
|
||
/** | ||
* Implementation of the RFC5869 HKDF-Expand function with the following | ||
* restrictions | ||
* | ||
* - secret is assumed to be always 32 bytes | ||
* - HASH is always SHA256 | ||
* | ||
* @param secret the input keying material (HMAC key) | ||
* @param info context and application specific information | ||
* @param info_len length of the info string | ||
* @param out output keying material | ||
* @param out_len length of output keying material | ||
*/ | ||
void | ||
ovpn_hkdf_expand(const uint8_t *secret, | ||
const uint8_t *info, int info_len, | ||
uint8_t *out, int out_len); | ||
|
||
/** | ||
* Variant of the RFC 8446 TLS 1.3 HKDF-Expand-Label function with the | ||
* following differences/restrictions: | ||
* - secret must 32 bytes in length | ||
* - label prefix is "ovpn " instead of "tls13 " | ||
* - HASH is always SHA256 | ||
* | ||
* @param secret Input secret | ||
* @param secret_len length of the input secret | ||
* @param label Label for the exported key material | ||
* @param label_len length of the label | ||
* @param context optional context | ||
* @param context_len length of the context | ||
* @param out output keying material | ||
* @param out_len length of output keying material | ||
* @return | ||
*/ | ||
bool | ||
ovpn_expand_label(const uint8_t *secret, size_t secret_len, | ||
const uint8_t *label, size_t label_len, | ||
const uint8_t *context, size_t context_len, | ||
uint8_t *out, uint16_t out_len); | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.