diff options
author | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-05-31 13:52:03 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@redhat.com> | 2017-06-01 08:52:58 +0200 |
commit | a46b5cb535a2ccb7a6ffa7672399182e094923c5 (patch) | |
tree | fdc9680f5ef54c061985f1285f02e6d51d2005c1 /lib/nettle/int | |
parent | 18f42d025c229ef5066245578f45c1771e1b6ec7 (diff) | |
download | gnutls-a46b5cb535a2ccb7a6ffa7672399182e094923c5.tar.gz |
prf: implement the TLS 1.0 and 1.2 PRFs using nettle
That simplifies the existing PRF code and moves it in the
crypto-backend component.
Signed-off-by: Nikos Mavrogiannopoulos <nmav@redhat.com>
Diffstat (limited to 'lib/nettle/int')
-rw-r--r-- | lib/nettle/int/tls1-prf.c | 169 | ||||
-rw-r--r-- | lib/nettle/int/tls1-prf.h | 50 |
2 files changed, 219 insertions, 0 deletions
diff --git a/lib/nettle/int/tls1-prf.c b/lib/nettle/int/tls1-prf.c new file mode 100644 index 0000000000..94228c6d7c --- /dev/null +++ b/lib/nettle/int/tls1-prf.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +/* Functions for the TLS PRF handling. + */ + +#if HAVE_CONFIG_H +# include <config.h> +#endif + +#include <gnutls_int.h> + +#include <stdlib.h> +#include <string.h> + +#include <nettle/hmac.h> +#include <nettle/memxor.h> +#include "int/tls1-prf.h" +#include <nettle/sha1.h> +#include <nettle/md5.h> + + +/* The RFC2246 P_hash() function. The mac_ctx is expected to + * be initialized and key set to be the secret key. + */ +static void +P_hash( void *mac_ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, + size_t seed_size, const uint8_t *seed, + size_t dst_length, + uint8_t *dst) +{ + uint8_t Atmp[MAX_HASH_SIZE]; + ssize_t left; + unsigned started = 0; + + /* round up */ + left = dst_length; + + while(left > 0) { + if (started == 0) { /* A(0) */ + update(mac_ctx, seed_size, seed); + started = 1; + } else { + update(mac_ctx, digest_size, Atmp); + } + digest(mac_ctx, digest_size, Atmp); /* store A(i) */ + + update(mac_ctx, digest_size, Atmp); /* hash A(i) */ + update(mac_ctx, seed_size, seed); /* hash seed */ + + if (left < (ssize_t)digest_size) + digest_size = left; + + digest(mac_ctx, digest_size, dst); + + left -= digest_size; + dst += digest_size; + } + + return; +} + +int +tls10_prf(size_t secret_size, const uint8_t *secret, + size_t label_size, const char *label, + size_t seed_size, const uint8_t *seed, + size_t length, uint8_t *dst) +{ + int l_s, cseed_size = seed_size + label_size; + const uint8_t *s1, *s2; + struct hmac_md5_ctx md5_ctx; + struct hmac_sha1_ctx sha1_ctx; + uint8_t o1[MAX_PRF_BYTES]; + uint8_t cseed[MAX_SEED_SIZE]; + + if (cseed_size > MAX_SEED_SIZE || length > MAX_PRF_BYTES) + return 0; + + memcpy(cseed, label, label_size); + memcpy(&cseed[label_size], seed, seed_size); + + l_s = secret_size / 2; + s1 = &secret[0]; + s2 = &secret[l_s]; + if (secret_size % 2 != 0) { + l_s++; + } + + hmac_md5_set_key(&md5_ctx, l_s, s1); + + P_hash(&md5_ctx, (nettle_hash_update_func*)hmac_md5_update, + (nettle_hash_digest_func*)hmac_md5_digest, + MD5_DIGEST_SIZE, + cseed_size, cseed, length, o1); + + hmac_sha1_set_key(&sha1_ctx, l_s, s2); + + P_hash(&sha1_ctx, (nettle_hash_update_func*)hmac_sha1_update, + (nettle_hash_digest_func*)hmac_sha1_digest, + SHA1_DIGEST_SIZE, + cseed_size, cseed, length, dst); + + memxor(dst, o1, length); + + return 1; +} + +/*- + * tls12_prf: + * @mac_ctx: a MAC context initialized with key being the secret + * @update: a MAC update function + * @digest: a MAC digest function + * @digest_size: the MAC output size + * @label_size: the size of the label + * @label: the label to apply + * @seed_size: the seed size + * @seed: the seed + * @length: size of desired PRF output + * @dst: the location to store output + * + * The TLS 1.2 Pseudo-Random-Function (PRF). + * + * Returns: zero on failure, non zero on success. + -*/ +int +tls12_prf(void *mac_ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, + size_t label_size, const char *label, + size_t seed_size, const uint8_t *seed, + size_t length, uint8_t *dst) +{ + size_t cseed_size = seed_size + label_size; + uint8_t cseed[MAX_SEED_SIZE]; + + if (cseed_size > MAX_SEED_SIZE) + return 0; + + memcpy(cseed, label, label_size); + memcpy(&cseed[label_size], seed, seed_size); + + P_hash(mac_ctx, update, digest, digest_size, + cseed_size, cseed, length, dst); + + return 1; +} diff --git a/lib/nettle/int/tls1-prf.h b/lib/nettle/int/tls1-prf.h new file mode 100644 index 0000000000..a455377571 --- /dev/null +++ b/lib/nettle/int/tls1-prf.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2017 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * The GnuTLS is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + * + */ + +#ifndef TLS_PRF_H_INCLUDED +#define TLS_PRF_H_INCLUDED + +#include <nettle/nettle-meta.h> + +#define MAX_SEED_SIZE 200 +#define MAX_PRF_BYTES 200 + +/* Namespace mangling */ +#define tls10_prf nettle_tls10_prf +#define tls12_prf nettle_tls12_prf + +int +tls10_prf(size_t secret_size, const uint8_t *secret, + size_t label_size, const char *label, + size_t seed_size, const uint8_t *seed, + size_t length, uint8_t *dst); + +int +tls12_prf(void *mac_ctx, + nettle_hash_update_func *update, + nettle_hash_digest_func *digest, + size_t digest_size, + size_t label_size, const char *label, + size_t seed_size, const uint8_t *seed, + size_t length, uint8_t *dst); + +#endif /* TLS_PRF_H_INCLUDED */ |