iPXE
tlskey.c File Reference

TLS key schedules. More...

#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <byteswap.h>
#include <ipxe/malloc.h>
#include <ipxe/hkdf.h>
#include <ipxe/hmac.h>
#include <ipxe/md5_sha1.h>
#include <ipxe/tlskey.h>

Go to the source code of this file.

Data Structures

struct  tls_phase
 A TLS traffic phase. More...
struct  tlskey_hello
 A ClientHello or ServerHello handshake record prefix of interest. More...
struct  tlskey_finished
 A Finished handshake record prefix of interest. More...

Macros

#define TLSKEY_HELLO_IDX(type)
 Calculate endpoint index from ClientHello or ServerHello record type.
#define TLSKEY_FINISHED   20
 Finished record type.
#define TLSKEY_HASH_VERIFY_MIN   12
 Minimum length for verification data.

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
int tlskey_start (struct tls_key_schedule *tlskey, const struct tls_key_schedule_operations *op, struct digest_algorithm *digest, const struct tls_random *nonce)
 Start key schedule.
void tlskey_stop (struct tls_key_schedule *tlskey)
 Stop key schedule.
static unsigned int tlskey_hello (struct tls_key_schedule *tlskey, const struct tlskey_hello *hello, unsigned int index)
 Process digested ClientHello or ServerHello handshake record.
static unsigned int tlskey_finished (struct tls_key_schedule *tlskey)
 Process digested Finished handshake record.
static unsigned int tlskey_handshake (struct tls_key_schedule *tlskey, const void *data, size_t len)
 Process digested handshake record.
void tlskey_digest (struct tls_key_schedule *tlskey, const void *data, size_t len)
 Add handshake to running transcript digest.
static void tlskey_expand (struct tls_key_schedule *tlskey, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
 Expand key material.
void tlskey_reset (struct tls_key_schedule *tlskey)
 Reset key schedule.
int tlskey_apply (struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
 Apply a new shared secret.
int tlskey_master (struct tls_key_schedule *tlskey, int ems)
 Generate master secret.
int tlskey_verify (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
 Generate verification data.
int tlskey_traffic (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
 Generate traffic secret.
int tlskey_cipher (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
 Generate cipher key material.
int tlskey_tbshash (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
 Generate signable digest value.
int tlskey_save (struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
 Save pre-shared key.
int tlskey_load (struct tls_key_schedule *tlskey, int ems, const struct tls_preshared_key *psk)
 Load pre-shared key.
int tlskey_bind (const struct tls_preshared_key *psk, const void *prefix, size_t prefix_len, void *binder, size_t binder_len)
 Generate pre-shared key binder value.
static size_t tlskey_hkdf_secretsize (struct digest_algorithm *digest)
 Calculate secret size.
static void tlskey_hkdf_expand (struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
 Expand key material.
static void tlskey_hkdf_empty (struct digest_algorithm *digest, void *empty)
 Calculate empty digest value.
static void tlskey_hkdf_finished (struct digest_algorithm *digest, const void *secret, const void *hash, void *out)
 Calculate a finished MAC.
static void tlskey_hkdf_reset (struct tls_key_schedule *tlskey)
 Reset key schedule.
static int tlskey_hkdf_apply (struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
 Apply a new shared secret.
static int tlskey_hkdf_master (struct tls_key_schedule *tlskey, int ems)
 Generate master secret.
static int tlskey_hkdf_verify (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
 Generate verification data.
static int tlskey_hkdf_traffic (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
 Generate traffic secret.
static int tlskey_hkdf_cipher (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac __unused, size_t mac_len)
 Generate cipher key material.
static int tlskey_hkdf_tbshash (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data __unused, size_t len, void *tbs)
 Generate signable digest value.
static int tlskey_hkdf_save (struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
 Save pre-shared key.
static int tlskey_hkdf_load (struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
 Load pre-shared key.
static int tlskey_hkdf_bind (const struct tls_preshared_key *psk, const void *hash, void *binder, size_t binder_len)
 Generate pre-shared key binder value.
static size_t tlskey_hash_secretsize (struct digest_algorithm *digest)
 Calculate secret size.
static void tlskey_hash_expand (struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
 Expand key material.
static void tlskey_hash_reset (struct tls_key_schedule *tlskey)
 Reset key schedule.
static int tlskey_hash_apply (struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
 Apply a new shared secret.
static int tlskey_hash_master (struct tls_key_schedule *tlskey, int ems)
 Generate master secret.
static int tlskey_hash_verify (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
 Generate verification data.
static int tlskey_hash_traffic (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
 Generate traffic secret.
static int tlskey_hash_cipher (struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
 Generate cipher key material.
static int tlskey_hash_tbshash (struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
 Generate signable digest value.
static int tlskey_hash_save (struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
 Save pre-shared key.
static int tlskey_hash_load (struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
 Load pre-shared key.
static int tlskey_hash_bind (const struct tls_preshared_key *psk __unused, const void *hash __unused, void *binder __unused, size_t binder_len)
 Generate pre-shared key binder value.
static size_t tlskey_md5_sha1_secretsize (struct digest_algorithm *digest)
 Calculate secret size.
static void tlskey_md5_sha1_expand (struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
 Expand key material.
static int tlskey_md5_sha1_apply (struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
 Apply a new shared secret.
static int tlskey_md5_sha1_save (struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
 Save pre-shared key.

Variables

const struct tls_endpoint tls_client
 Client endpoint.
const struct tls_endpoint tls_server
 Server endpoint.
static const struct tls_endpoint * tls_endpoint []
 Endpoint list.
const struct tls_phase tls_early
 Early traffic phase.
const struct tls_phase tls_handshake
 Handshake traffic phase.
const struct tls_phase tls_application
 Application traffic phase.
const struct tls_key_schedule_operations tlskey_hkdf
 TLS key schedule based on HKDF.
const struct tls_key_schedule_operations tlskey_hash
 TLS key schedule based on P_Hash().
const struct tls_key_schedule_operations tlskey_md5_sha1
 TLS key schedule based on P_MD5()+P_SHA1().

Detailed Description

TLS key schedules.

The TLS key schedule is responsible for maintaining the running handshake transcript digest, for deriving key material from the shared secret that was negotiated by a key exchange mechanism, and for performing all cryptographic calculations required by the TLS protocol.

A single abstraction of a key schedule is defined that is independent of the TLS protocol version. Three implementations of this abstraction are provided:

  • a TLS version 1.3 key schedule using HKDF
  • a TLS version 1.2 key schedule using PRF based on P_Hash()
  • a TLS version 1.0/1.1 key schedule using PRF based on P_MD5()+P_SHA1()

The basic set of operations is as required by the TLS protocol:

  • Start the key schedule by specifying the key schedule implementation to be used along with the handshake digest algorithm
  • Add each handshake record to the running transcript digest
  • Apply a shared secret (e.g. a pre-master secret that was agreed using Ephemeral Diffie-Hellman key exchange)
  • Derive a master secret from the shared secret
  • Derive client and server verification data for the Finished handshake records
  • Derive cipher keys, fixed IVs, and MAC secrets
  • Derive digest values to be signed or verified (e.g. for CertificateVerify and ServerKeyExchange)
  • Save pre-shared key for future session resumption
  • Load pre-shared key to resume a session

The key schedule is responsible only for raw key material: it has no notion of the peer identity and so is fundamentally anonymous in nature.

The separate secure channel abstraction handles all concepts of peer identity. The key schedule provides the cryptographic operations and properties that are documented as required by the secure channel, e.g. the calculations required to demonstrate or verify possession of key material.

Definition in file tlskey.c.

Macro Definition Documentation

◆ TLSKEY_HELLO_IDX

#define TLSKEY_HELLO_IDX ( type)
Value:
( (type) - 1 )
uint32_t type
Operating system type.
Definition ena.h:1

Calculate endpoint index from ClientHello or ServerHello record type.

Definition at line 287 of file tlskey.c.

Referenced by tlskey_handshake().

◆ TLSKEY_FINISHED

#define TLSKEY_FINISHED   20

Finished record type.

Definition at line 295 of file tlskey.c.

Referenced by tlskey_handshake().

◆ TLSKEY_HASH_VERIFY_MIN

#define TLSKEY_HASH_VERIFY_MIN   12

Minimum length for verification data.

Definition at line 1405 of file tlskey.c.

Referenced by tlskey_hash_verify().

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ tlskey_start()

int tlskey_start ( struct tls_key_schedule * tlskey,
const struct tls_key_schedule_operations * op,
struct digest_algorithm * digest,
const struct tls_random * nonce )

Start key schedule.

Parameters
tlskeyKey schedule
opKey schedule operations
digestDigest algorithm
nonceLocal endpoint random bytes
Return values
rcReturn status code

The random bytes must be the random bytes that the local endpoint will subsequently incorporate within its own ClientHello (or ServerHello, if acting as a server). The caller must guarantee that these are fresh and are unpredictable by the peer. A freshly generated secure channel ephemeral secret can be used to fulfil this requirement.

Definition at line 180 of file tlskey.c.

183 {
184 size_t digestsize = digest->digestsize;
185 size_t ctxsize = digest->ctxsize;
186 size_t secretsize;
187 size_t total;
188 void *dynamic;
189 int rc;
190
191 /* Stop any existing running key schedule */
192 tlskey_stop ( tlskey );
193
194 /* Sanity check */
195 if ( ! digestsize ) {
196 rc = -ENOTTY;
197 goto err_sanity;
198 }
199
200 /* Determine required sizes */
201 secretsize = op->secretsize ( digest );
202 if ( ! secretsize ) {
203 DBGC ( tlskey, "TLSKEY %p cannot use %s with %s\n",
204 tlskey, op->name, digest->name );
205 rc = -ENOTSUP;
206 goto err_secretsize;
207 }
208 total = ( secretsize + /* secret */
209 ctxsize + /* transcript.ctx */
210 digestsize + /* transcript.running */
211 digestsize /* transcript.finishing */ );
212
213 /* Allocate dynamic storage */
214 dynamic = zalloc ( total );
215 if ( ! dynamic ) {
216 rc = -ENOMEM;
217 goto err_alloc;
218 }
219
220 /* Initialise schedule */
221 tlskey->op = op;
222 tlskey->digest = digest;
223 tlskey->secretsize = secretsize;
224 DBGC ( tlskey, "TLSKEY %p using %s with %s\n",
225 tlskey, tlskey->op->name, tlskey->digest->name );
226
227 /* Assign dynamic storage */
228 tlskey->dynamic = dynamic;
229 tlskey->secret = dynamic; dynamic += secretsize;
230 tlskey->transcript.ctx = dynamic; dynamic += ctxsize;
231 tlskey->transcript.running = dynamic; dynamic += digestsize;
232 tlskey->transcript.finishing = dynamic; dynamic += digestsize;
233 assert ( dynamic == ( tlskey->dynamic + total ) );
234
235 /* Initialise transcript digest */
236 digest_init ( digest, tlskey->transcript.ctx );
237 tlskey_digest ( tlskey, NULL, 0 );
238 memcpy ( &tlskey->nonce, nonce, sizeof ( tlskey->nonce ) );
239 DBGC ( tlskey, "TLSKEY %p local nonce:\n", tlskey );
240 DBGC_HDA ( tlskey, 0, &tlskey->nonce, sizeof ( tlskey->nonce ) );
241
242 /* Reset key schedule */
243 tlskey_reset ( tlskey );
244
245 return 0;
246
247 tlskey_stop ( tlskey );
248 err_alloc:
249 err_secretsize:
250 err_sanity:
251 return rc;
252}
#define NULL
NULL pointer (VOID *).
Definition Base.h:321
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:61
#define DBGC(...)
Definition compiler.h:530
#define DBGC_HDA(...)
Definition compiler.h:531
#define ENOMEM
Not enough space.
Definition errno.h:578
#define ENOTSUP
Operation not supported.
Definition errno.h:633
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:638
static void digest_init(struct digest_algorithm *digest, void *ctx)
Definition crypto.h:294
void * memcpy(void *dest, const void *src, size_t len) __nonnull
void * zalloc(size_t size)
Allocate cleared memory.
Definition malloc.c:718
static uint16_t struct vmbus_xfer_pages_operations * op
Definition netvsc.h:327
uint32_t digestsize
Digest size (i.e.
Definition pccrr.h:1
size_t digestsize
Digest size.
Definition crypto.h:27
size_t ctxsize
Context size.
Definition crypto.h:23
const char * name
Algorithm name.
Definition crypto.h:21
const char * name
Name.
Definition tlskey.h:172
const struct tls_key_schedule_operations * op
Key schedule operations.
Definition tlskey.h:102
void * secret
Secret(s).
Definition tlskey.h:111
size_t secretsize
Secret size.
Definition tlskey.h:106
struct tls_transcript transcript
Running handshake transcript digest.
Definition tlskey.h:116
struct tls_random nonce
Local endpoint random bytes.
Definition tlskey.h:118
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:104
void * dynamic
Dynamically-allocated storage.
Definition tlskey.h:109
void * finishing
Running digest value up to the most recent Finished (if any).
Definition tlskey.h:63
void * running
Running digest value.
Definition tlskey.h:52
void * ctx
Digest context.
Definition tlskey.h:44
void tlskey_stop(struct tls_key_schedule *tlskey)
Stop key schedule.
Definition tlskey.c:259
void tlskey_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:492
void tlskey_digest(struct tls_key_schedule *tlskey, const void *data, size_t len)
Add handshake to running transcript digest.
Definition tlskey.c:416
u8 nonce[32]
Nonce value.
Definition wpa.h:25

References assert, tls_transcript::ctx, digest_algorithm::ctxsize, DBGC, DBGC_HDA, tls_key_schedule::digest, digest_init(), digest_algorithm::digestsize, digestsize, tls_key_schedule::dynamic, ENOMEM, ENOTSUP, ENOTTY, tls_transcript::finishing, memcpy(), digest_algorithm::name, tls_key_schedule_operations::name, nonce, tls_key_schedule::nonce, NULL, op, tls_key_schedule::op, rc, tls_transcript::running, tls_key_schedule::secret, tls_key_schedule::secretsize, tlskey_digest(), tlskey_reset(), tlskey_stop(), tls_key_schedule::transcript, and zalloc().

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), and tls_set_digest().

◆ tlskey_stop()

void tlskey_stop ( struct tls_key_schedule * tlskey)

Stop key schedule.

Parameters
tlskeyKey schedule

Definition at line 259 of file tlskey.c.

259 {
260
261 /* Clear and free any dynamic storage */
262 zfree ( tlskey->dynamic );
263
264 /* Clear key schedule contents */
265 memset ( tlskey, 0, sizeof ( *tlskey ) );
266
267 /* Set null digest algorithm */
268 tlskey->digest = &digest_null;
269}
struct digest_algorithm digest_null
Definition crypto_null.c:53
void * memset(void *dest, int character, size_t len) __nonnull
void zfree(void *ptr)
Clear and free memory.
Definition malloc.c:738

References tls_key_schedule::digest, digest_null, tls_key_schedule::dynamic, memset(), and zfree().

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_clear_digest(), and tlskey_start().

◆ tlskey_hello()

unsigned int tlskey_hello ( struct tls_key_schedule * tlskey,
const struct tlskey_hello * hello,
unsigned int index )
static

Process digested ClientHello or ServerHello handshake record.

Parameters
tlskeyKey schedule
helloClientHello or ServerHello handshake record
indexEndpoint index
Return values
flagsAdditional transcript flags to set

Definition at line 305 of file tlskey.c.

307 {
308 const struct tls_endpoint *end = tls_endpoint[index];
309 const struct tls_random *nonce = &tlskey->nonce;
310 struct tls_random *random = &tlskey->random[index];
311 unsigned int flags = 0;
312
313 /* We check that the local endpoint random bytes have been
314 * incorporated into the running transcript digest, since this
315 * is required in order to provide our non-replayability
316 * guarantees.
317 */
318 if ( memcmp ( nonce, &hello->random, sizeof ( *nonce ) ) == 0 )
320
321 /* We also capture and store the client and server random
322 * bytes from these records, since TLS versions 1.2 and
323 * earlier sometimes require these values separately from the
324 * full running transcript digest.
325 */
326 memcpy ( random, &hello->random, sizeof ( *random ) );
327
328 DBGC ( tlskey, "TLSKEY %p %s random bytes%s:\n", tlskey, end->name,
329 ( ( flags & TLSKEY_TSF_NONCED ) ? " (local nonce)" : "" ) );
330 DBGC_HDA ( tlskey, 0, random, sizeof ( *random ) );
331 return flags;
332}
long index
Definition bigint.h:30
uint8_t flags
Flags.
Definition ena.h:7
uint32_t end
Ending offset.
Definition netvsc.h:7
long int random(void)
Generate a pseudo-random number between 0 and 2147483647L or 2147483562?
Definition random.c:32
uint16_t hello
Hello time.
Definition stp.h:27
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition string.c:115
A TLS endpoint.
Definition tlskey.h:19
struct tls_random random[2]
Client and server random bytes.
Definition tlskey.h:120
TLS client or server random bytes.
Definition tlskey.h:36
#define TLSKEY_TSF_NONCED
Transcript digest includes a Hello record containing the local nonce.
Definition tlskey.h:69

References DBGC, DBGC_HDA, end, flags, hello, index, memcmp(), memcpy(), nonce, tls_key_schedule::nonce, random(), tls_key_schedule::random, and TLSKEY_TSF_NONCED.

Referenced by tlskey_handshake().

◆ tlskey_finished()

unsigned int tlskey_finished ( struct tls_key_schedule * tlskey)
static

Process digested Finished handshake record.

Parameters
tlskeyKey schedule
Return values
flagsAdditional transcript flags to set

Definition at line 340 of file tlskey.c.

340 {
341 struct tls_transcript *transcript = &tlskey->transcript;
342 struct digest_algorithm *digest = tlskey->digest;
343 size_t digestsize = digest->digestsize;
344
345 /* The TLS version 1.3 key schedule derives application
346 * traffic secrets from the transcript hash up to and
347 * including only the server Finished, but requires the
348 * handshake traffic secret to remain available for
349 * calculating the client Finished.
350 *
351 * If there are any intervening handshake records (e.g. an
352 * EndOfEarlyData) then this makes it impossible to construct
353 * the client application traffic secret without either:
354 *
355 * - retaining a separate record of the transcript hash up
356 * to and including the server Finished, or
357 *
358 * - retaining the client handshake traffic secret after
359 * calculating the client application traffic secret.
360 *
361 * The TLS version 1.3 key schedule also derives resumption
362 * secrets from NewSessionTicket handshake records that arrive
363 * after the client Finished, but using the transcript hash up
364 * to and including only the client Finished.
365 *
366 * We choose to solve both of these problems simultaneously by
367 * retaining a second "finishing" digest value that mirrors
368 * the continuously running digest value until the first
369 * Finished is digested, and then switches to updating only
370 * when a new Finished is digested.
371 */
372 DBGC ( tlskey, "TLSKEY %p finishing digest:\n", tlskey );
373 DBGC_HDA ( tlskey, 0, transcript->running, digestsize );
374 return TLSKEY_TSF_FINISHED;
375}
A message digest algorithm.
Definition crypto.h:19
A TLS running handshake transcript digest.
Definition tlskey.h:42
#define TLSKEY_TSF_FINISHED
Transcript digest includes a Finished record.
Definition tlskey.h:72

References DBGC, DBGC_HDA, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, tls_transcript::running, TLSKEY_TSF_FINISHED, and tls_key_schedule::transcript.

Referenced by tlskey_handshake().

◆ tlskey_handshake()

unsigned int tlskey_handshake ( struct tls_key_schedule * tlskey,
const void * data,
size_t len )
static

Process digested handshake record.

Parameters
tlskeyKey schedule
dataHandshake record
lenLength of handshake record
Return values
flagsAdditional transcript flags to set

Definition at line 385 of file tlskey.c.

386 {
387 const struct tlskey_hello *hello;
388 const struct tlskey_finished *finished;
389 unsigned int index;
390
391 /* Check for ClientHello and ServerHello */
392 if ( len >= sizeof ( *hello ) ) {
393 hello = data;
394 index = TLSKEY_HELLO_IDX ( hello->type );
395 if ( ( index == TLS_CLIENT ) || ( index == TLS_SERVER ) )
396 return tlskey_hello ( tlskey, hello, index );
397 }
398
399 /* Check for Finished */
400 if ( len >= sizeof ( *finished ) ) {
401 finished = data;
402 if ( finished->type == TLSKEY_FINISHED )
403 return tlskey_finished ( tlskey );
404 }
405
406 return 0;
407}
ring len
Length.
Definition dwmac.h:226
uint8_t data[48]
Additional event data.
Definition ena.h:11
A Finished handshake record prefix of interest.
Definition tlskey.c:290
uint8_t type
Definition tlskey.c:291
A ClientHello or ServerHello handshake record prefix of interest.
Definition tlskey.c:279
#define TLSKEY_FINISHED
Finished record type.
Definition tlskey.c:295
#define TLSKEY_HELLO_IDX(type)
Calculate endpoint index from ClientHello or ServerHello record type.
Definition tlskey.c:287
static unsigned int tlskey_hello(struct tls_key_schedule *tlskey, const struct tlskey_hello *hello, unsigned int index)
Process digested ClientHello or ServerHello handshake record.
Definition tlskey.c:305
static unsigned int tlskey_finished(struct tls_key_schedule *tlskey)
Process digested Finished handshake record.
Definition tlskey.c:340
#define TLS_CLIENT
Client endpoint index.
Definition tlskey.h:27
#define TLS_SERVER
Server endpoint index.
Definition tlskey.h:30

References data, hello, index, len, TLS_CLIENT, TLS_SERVER, TLSKEY_FINISHED, tlskey_finished(), tlskey_hello(), TLSKEY_HELLO_IDX, and tlskey_finished::type.

Referenced by tlskey_digest().

◆ tlskey_digest()

void tlskey_digest ( struct tls_key_schedule * tlskey,
const void * data,
size_t len )

Add handshake to running transcript digest.

Parameters
tlskeyKey schedule
dataHandshake record
lenLength of handshake record

Definition at line 416 of file tlskey.c.

417 {
418 struct tls_transcript *transcript = &tlskey->transcript;
419 struct digest_algorithm *digest = tlskey->digest;
420 size_t digestsize = digest->digestsize;
421 size_t ctxsize = digest->ctxsize;
422 unsigned int flags;
423 struct {
425 } tmp;
426
427 /* Append to running transcript digest */
428 digest_update ( digest, transcript->ctx, data, len );
429
430 /* Update running transcript digest output */
431 memcpy ( tmp.ctx, transcript->ctx, ctxsize );
432 digest_final ( digest, tmp.ctx, transcript->running );
433
434 /* Process digested handshake record */
435 flags = tlskey_handshake ( tlskey, data, len );
436 transcript->flags |= flags;
437
438 /* Update the finishing digest value, if applicable */
439 if ( ! ( ( transcript->flags ^ flags ) & TLSKEY_TSF_FINISHED ) ) {
440 memcpy ( transcript->finishing, transcript->running,
441 digestsize );
442 }
443
444 /* Clear temporary secrets */
445 memset ( &tmp, 0, sizeof ( tmp ) );
446}
struct golan_eq_context ctx
Definition CIB_PRM.h:0
unsigned char uint8_t
Definition stdint.h:10
static void digest_final(struct digest_algorithm *digest, void *ctx, void *out)
Definition crypto.h:305
static void digest_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Definition crypto.h:299
unsigned long tmp
Definition linux_pci.h:65
unsigned int flags
Transcript flags.
Definition tlskey.h:65
static unsigned int tlskey_handshake(struct tls_key_schedule *tlskey, const void *data, size_t len)
Process digested handshake record.
Definition tlskey.c:385

References ctx, tls_transcript::ctx, digest_algorithm::ctxsize, data, tls_key_schedule::digest, digest_final(), digest_update(), digest_algorithm::digestsize, digestsize, tls_transcript::finishing, flags, tls_transcript::flags, len, memcpy(), memset(), tls_transcript::running, tlskey_handshake(), TLSKEY_TSF_FINISHED, tmp, and tls_key_schedule::transcript.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_add_handshake(), and tlskey_start().

◆ tlskey_expand()

void tlskey_expand ( struct tls_key_schedule * tlskey,
const void * secret,
const char * label,
const void * seed,
size_t seed_len,
void * out,
size_t out_len )
static

Expand key material.

Parameters
tlskeyKey schedule
secretSecret
labelLabel string
seedSeed material
seed_lenLength of seed material
outOutput buffer
out_lenLength of output buffer

Definition at line 466 of file tlskey.c.

469 {
470 const struct tls_key_schedule_operations *op = tlskey->op;
471 struct digest_algorithm *digest = tlskey->digest;
472
473 /* Sanity check */
474 assert ( op != NULL );
475
476 /* Expand key material */
477 DBGC2 ( tlskey, "TLSKEY %p expanding seed \"%s\":\n", tlskey, label );
478 DBGC2_HDA ( tlskey, 0, seed, seed_len );
479 op->expand ( digest, secret, label, seed, seed_len, out, out_len );
480 DBGC2 ( tlskey, "TLSKEY %p expanded:\n", tlskey );
481 DBGC2_HDA ( tlskey, 0, out, out_len );
482}
__be32 out[4]
Definition CIB_PRM.h:8
#define DBGC2(...)
Definition compiler.h:547
#define DBGC2_HDA(...)
Definition compiler.h:548
A text label widget.
Definition label.h:16
TLS key schedule operations.
Definition tlskey.h:170

References assert, DBGC2, DBGC2_HDA, tls_key_schedule::digest, NULL, op, tls_key_schedule::op, and out.

Referenced by tlskey_hash_cipher(), tlskey_hash_master(), tlskey_hash_verify(), tlskey_hkdf_apply(), tlskey_hkdf_cipher(), tlskey_hkdf_save(), and tlskey_hkdf_traffic().

◆ tlskey_reset()

void tlskey_reset ( struct tls_key_schedule * tlskey)

Reset key schedule.

Parameters
tlskeyKey schedule

It is safe to reset a key schedule that has been stopped, or that has not yet been started.

Definition at line 492 of file tlskey.c.

492 {
493 const struct tls_key_schedule_operations *op = tlskey->op;
494
495 /* Do nothing if key schedule is stopped */
496 if ( ! op ) {
497 assert ( tlskey->secretsize == 0 );
498 assert ( tlskey->kdf.flags == 0 );
499 assert ( tlskey->traffic[TLS_CLIENT].phase == NULL );
500 assert ( tlskey->traffic[TLS_SERVER].phase == NULL );
501 return;
502 }
503
504 /* Clear secrets, flags, and traffic phases */
505 memset ( tlskey->secret, 0, tlskey->secretsize );
506 tlskey->kdf.flags = 0;
507 tlskey->traffic[TLS_CLIENT].phase = NULL;
508 tlskey->traffic[TLS_SERVER].phase = NULL;
509
510 /* Reset key schedule */
511 op->reset ( tlskey );
512}
unsigned int flags
Key flags.
Definition tlskey.h:79
struct tls_traffic_secret traffic[2]
Traffic secrets.
Definition tlskey.h:124
struct tls_kdf_secret kdf
Key derivation function secret.
Definition tlskey.h:122
const struct tls_phase * phase
Phase.
Definition tlskey.h:96

References assert, tls_kdf_secret::flags, tls_key_schedule::kdf, memset(), NULL, op, tls_key_schedule::op, tls_traffic_secret::phase, tls_key_schedule::secret, tls_key_schedule::secretsize, TLS_CLIENT, TLS_SERVER, and tls_key_schedule::traffic.

Referenced by tls_channel_reset(), tlskey_load(), and tlskey_start().

◆ tlskey_apply()

int tlskey_apply ( struct tls_key_schedule * tlskey,
const void * shared,
size_t shared_len )

Apply a new shared secret.

Parameters
tlskeyKey schedule
sharedNew shared secret
shared_lenLength of new shared secret
Return values
rcReturn status code

Definition at line 522 of file tlskey.c.

523 {
524 const struct tls_key_schedule_operations *op = tlskey->op;
525 int rc;
526
527 /* Sanity check */
528 if ( ! op )
529 return -ENOTTY;
530
531 /* All schedules define the master secret as immutable */
532 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
533 DBGC ( tlskey, "TLSKEY %p cannot apply a new shared secret "
534 "after generating master secret\n", tlskey );
535 return -EPROTO;
536 }
537
538 /* Apply new shared secret */
539 DBGC ( tlskey, "TLSKEY %p applying secret:\n", tlskey );
540 DBGC_HDA ( tlskey, 0, shared, shared_len );
541 if ( ( rc = op->apply ( tlskey, shared, shared_len ) ) != 0 )
542 return rc;
543
544 /* Mark key schedule as containing key material */
545 tlskey->kdf.flags |= TLSKEY_KDF_KEYED;
546
547 return 0;
548}
#define EPROTO
Protocol error.
Definition errno.h:668
#define TLSKEY_KDF_MASTER
Key derivation function has a master secret.
Definition tlskey.h:86
#define TLSKEY_KDF_KEYED
Key derivation function has key material.
Definition tlskey.h:83

References DBGC, DBGC_HDA, ENOTTY, EPROTO, tls_kdf_secret::flags, tls_key_schedule::kdf, op, tls_key_schedule::op, rc, TLSKEY_KDF_KEYED, and TLSKEY_KDF_MASTER.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_channel_apply(), tlskey_hash_load(), tlskey_hash_master(), and tlskey_hkdf_master().

◆ tlskey_master()

int tlskey_master ( struct tls_key_schedule * tlskey,
int ems )

Generate master secret.

Parameters
tlskeyKey schedule
emsExtended master secret extension is enabled
Return values
rcReturn status code

Definition at line 557 of file tlskey.c.

557 {
558 const struct tls_key_schedule_operations *op = tlskey->op;
559 int rc;
560
561 /* Sanity check */
562 if ( ! op )
563 return -ENOTTY;
564
565 /* Any conceivable schedule requires key material */
566 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
567 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
568 "without key material\n", tlskey );
569 return -EPROTO;
570 }
571
572 /* All schedules define the master secret as immutable */
573 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
574 DBGC ( tlskey, "TLSKEY %p cannot regenerate master secret\n",
575 tlskey );
576 return -EPROTO;
577 }
578
579 /* Generate master secret */
580 DBGC ( tlskey, "TLSKEY %p generating %smaster secret\n",
581 tlskey, ( ems ? "extended " : "" ) );
582 if ( ( rc = op->master ( tlskey, ems ) ) != 0 )
583 return rc;
584
585 /* Mark key schedule as containing master secret */
586 tlskey->kdf.flags |= TLSKEY_KDF_MASTER;
587 if ( ems )
588 tlskey->kdf.flags |= TLSKEY_KDF_EMS;
589
590 return 0;
591}
#define TLSKEY_KDF_EMS
Key derivation function has an extended master secret.
Definition tlskey.h:89

References DBGC, ENOTTY, EPROTO, tls_kdf_secret::flags, tls_key_schedule::kdf, op, tls_key_schedule::op, rc, TLSKEY_KDF_EMS, TLSKEY_KDF_KEYED, and TLSKEY_KDF_MASTER.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_new_finished(), and tls_send_client_key_exchange().

◆ tlskey_verify()

int tlskey_verify ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
void * verify,
size_t verify_len )

Generate verification data.

Parameters
tlskeyKey schedule
endVerification endpoint
verifyVerification data to fill in
verify_lenLength of verification data
Return values
rcReturn status code

Definition at line 602 of file tlskey.c.

604 {
605 const struct tls_key_schedule_operations *op = tlskey->op;
606 int rc;
607
608 /* Sanity check */
609 if ( ! op )
610 return -ENOTTY;
611
612 /* Verification data must be non-replayable */
613 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
614 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
615 "without a digested nonce\n", tlskey );
616 return -EPROTO;
617 }
618
619 /* Generate verification data */
620 DBGC2 ( tlskey, "TLSKEY %p generating %s verification data\n",
621 tlskey, end->name );
622 if ( ( rc = op->verify ( tlskey, end, verify, verify_len ) ) != 0 )
623 return rc;
624 DBGC ( tlskey, "TLSKEY %p %s verification data:\n",
625 tlskey, end->name );
626 DBGC_HDA ( tlskey, 0, verify, verify_len );
627
628 return 0;
629}
int(* verify)(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.h:243

References DBGC, DBGC2, DBGC_HDA, end, ENOTTY, EPROTO, tls_transcript::flags, op, tls_key_schedule::op, rc, TLSKEY_TSF_NONCED, tls_key_schedule::transcript, and tls_key_schedule_operations::verify.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_channel_verify(), and tls_send_finished().

◆ tlskey_traffic()

int tlskey_traffic ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
const struct tls_phase * phase )

Generate traffic secret.

Parameters
tlskeyKey schedule
writerWriter endpoint
phaseTraffic phase
Return values
rcReturn status code

Definition at line 639 of file tlskey.c.

641 {
642 const struct tls_key_schedule_operations *op = tlskey->op;
643 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
644 unsigned int missing;
645 int rc;
646
647 /* Sanity check */
648 if ( ! op )
649 return -ENOTTY;
650
651 /* Check flags required for this traffic phase */
653 missing = ( ( tlskey->kdf.flags ^ phase->flags ) & phase->flags );
654 if ( missing ) {
655 DBGC ( tlskey, "TLSKEY %p cannot generate %s %s traffic "
656 "secrets (missing KDF flags %#04x)\n",
657 tlskey, writer->name, phase->name, missing );
658 return -EPROTO;
659 }
660
661 /* Generate traffic secret */
662 DBGC2 ( tlskey, "TLSKEY %p generating %s %s traffic secret\n",
663 tlskey, writer->name, phase->name );
664 if ( ( rc = op->traffic ( tlskey, writer, phase ) ) != 0 )
665 return rc;
666
667 /* Record phase */
668 traffic->phase = phase;
669
670 return 0;
671}
uint8_t index
Endpoint index.
Definition tlskey.h:21
const char name[7]
Name (for key expansion labels).
Definition tlskey.h:23
const char * name
Name.
Definition tlskey.c:129
uint8_t flags
Required key derivation function flags.
Definition tlskey.c:133
A TLS traffic secret.
Definition tlskey.h:92

References assert, DBGC, DBGC2, ENOTTY, EPROTO, tls_kdf_secret::flags, tls_phase::flags, tls_endpoint::index, tls_key_schedule::kdf, tls_endpoint::name, tls_phase::name, op, tls_key_schedule::op, tls_traffic_secret::phase, rc, TLSKEY_KDF_KEYED, and tls_key_schedule::traffic.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), and tls_prep_cipher().

◆ tlskey_cipher()

int tlskey_cipher ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
void * key,
size_t key_len,
void * iv,
size_t iv_len,
void * mac,
size_t mac_len )

Generate cipher key material.

Parameters
tlskeyKey schedule
writerWriter endpoint
keyCipher key to fill in
key_lenLength of cipher key
ivFixed portion of initialisation vector to fill in
iv_lenLength of fixed portion of initialisation vector
macMAC secret to fill in
mac_lenLength of MAC secret
Return values
rcReturn status code

For key schedules that include a ratchet mechanism, each call consumes the current generation of traffic secret and replaces it with the next generation. Repeated calls may therefore be used to obtain multiple generations of the cipher key material.

Definition at line 691 of file tlskey.c.

694 {
695 const struct tls_key_schedule_operations *op = tlskey->op;
696 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
697 int rc;
698
699 /* Sanity check */
700 if ( ! op )
701 return -ENOTTY;
702
703 /* Ensure that traffic secret has actually been generated */
704 if ( ! traffic->phase ) {
705 DBGC ( tlskey, "TLSKEY %p cannot generate cipher key "
706 "material without traffic secrets\n", tlskey );
707 return -EPROTO;
708 }
709
710 /* Generate cipher key material */
711 DBGC2 ( tlskey, "TLSKEY %p generating %s %s cipher key material\n",
712 tlskey, writer->name, traffic->phase->name );
713 if ( ( rc = op->cipher ( tlskey, writer, key, key_len, iv, iv_len,
714 mac, mac_len ) ) != 0 ) {
715 return rc;
716 }
717 if ( key_len ) {
718 DBGC ( tlskey, "TLSKEY %p %s key:\n", tlskey, writer->name );
719 DBGC_HDA ( tlskey, 0, key, key_len );
720 }
721 if ( iv_len ) {
722 DBGC ( tlskey, "TLSKEY %p %s IV:\n", tlskey, writer->name );
723 DBGC_HDA ( tlskey, 0, iv, iv_len );
724 }
725 if ( mac_len ) {
726 DBGC ( tlskey, "TLSKEY %p %s MAC:\n", tlskey, writer->name );
727 DBGC_HDA ( tlskey, 0, mac, mac_len );
728 }
729
730 return 0;
731}
union @162305117151260234136356364136041353210355154177 key
uint8_t mac[ETH_ALEN]
MAC address.
Definition ena.h:13
u8 iv[16]
Initialization vector.
Definition wpa.h:33

References DBGC, DBGC2, DBGC_HDA, ENOTTY, EPROTO, tls_endpoint::index, iv, key, mac, tls_endpoint::name, tls_phase::name, op, tls_key_schedule::op, tls_traffic_secret::phase, rc, and tls_key_schedule::traffic.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), and tls_change_cipher().

◆ tlskey_tbshash()

int tlskey_tbshash ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
struct digest_algorithm * digest,
const void * data,
size_t len,
void * tbs )

Generate signable digest value.

Parameters
tlskeyKey schedule
endEndpoint
digestSignature digest algorithm
dataAdditional data
lenLength of additional data
tbsSignable digest value to fill in
Return values
rcReturn status code

Definition at line 744 of file tlskey.c.

747 {
748 const struct tls_key_schedule_operations *op = tlskey->op;
749 int rc;
750
751 /* Sanity check */
752 if ( ! op )
753 return -ENOTTY;
754
755 /* Signable digest values must be non-replayable */
756 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
757 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
758 "without a digested nonce\n", tlskey );
759 return -EPROTO;
760 }
761
762 /* Signable digest values must be constructed over the
763 * parameters used to establish a shared secret, and so a
764 * shared secret must exist.
765 */
766 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
767 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
768 "without a shared secret\n", tlskey );
769 return -EPROTO;
770 }
771
772 /* Generate digest value */
773 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
774 tlskey, end->name, digest->name );
775 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
776 tbs ) ) != 0 ) {
777 return rc;
778 }
779 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
780 tlskey, end->name, digest->name );
781 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
782
783 return 0;
784}

References data, DBGC, DBGC2, DBGC_HDA, digest_algorithm::digestsize, end, ENOTTY, EPROTO, tls_kdf_secret::flags, tls_transcript::flags, tls_key_schedule::kdf, len, digest_algorithm::name, op, tls_key_schedule::op, rc, TLSKEY_KDF_KEYED, TLSKEY_TSF_NONCED, and tls_key_schedule::transcript.

Referenced by dummy_hash(), rfc8448_simple_test(), tls_key_verify(), and tls_send_certificate_verify().

◆ tlskey_save()

int tlskey_save ( struct tls_key_schedule * tlskey,
const void * nonce,
size_t nonce_len,
struct tls_preshared_key * psk )

Save pre-shared key.

Parameters
tlskeyKey schedule
nonceTicket nonce
nonce_lenLength of ticket nonce
pskPre-shared key to fill in
Return values
rcReturn status code

Definition at line 795 of file tlskey.c.

796 {
797 const struct tls_key_schedule_operations *op = tlskey->op;
798 struct digest_algorithm *digest = tlskey->digest;
799 int rc;
800
801 /* Clear any existing pre-shared key */
802 memset ( psk, 0, sizeof ( *psk ) );
803
804 /* Sanity check */
805 if ( ! op )
806 return -ENOTTY;
807
808 /* Session resumption requires a master secret */
809 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
810 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
811 "secret\n", tlskey );
812 return -EPROTO;
813 }
814
815 /* Save key material */
816 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
817 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
818 return rc;
819 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
820 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
821
822 /* Record key properties */
823 psk->op = op;
824 psk->digest = digest;
825 psk->flags = tlskey->kdf.flags;
826
827 return 0;
828}
struct digest_algorithm * digest
Digest algorithm (if set).
Definition tlskey.h:132
unsigned int flags
Key flags.
Definition tlskey.h:134
union tls_preshared_key::@022173016027117201055347232316162256252261104170 key
Key material.
const struct tls_key_schedule_operations * op
Key schedule operations (if set).
Definition tlskey.h:130

References DBGC, DBGC2, DBGC_HDA, tls_key_schedule::digest, tls_preshared_key::digest, ENOTTY, EPROTO, tls_kdf_secret::flags, tls_preshared_key::flags, tls_key_schedule::kdf, tls_preshared_key::key, memset(), nonce, op, tls_key_schedule::op, tls_preshared_key::op, rc, and TLSKEY_KDF_MASTER.

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_simple_test(), and tls_channel_save().

◆ tlskey_load()

int tlskey_load ( struct tls_key_schedule * tlskey,
int ems,
const struct tls_preshared_key * psk )

Load pre-shared key.

Parameters
tlskeyKey schedule
emsExtended master secret extension is enabled
pskPre-shared key
Return values
rcReturn status code

Definition at line 838 of file tlskey.c.

839 {
840 const struct tls_key_schedule_operations *op = tlskey->op;
841 struct digest_algorithm *digest = tlskey->digest;
842 int rc;
843
844 /* Reset key schedule */
845 tlskey_reset ( tlskey );
846
847 /* Sanity check */
848 if ( ! op )
849 return -ENOTTY;
850
851 /* Session resumption requires a master secret */
852 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
853 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
854 "secret\n", tlskey );
855 return -EPROTO;
856 }
857
858 /* Pre-shared key must match extended/non-extended usage */
859 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
860 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
861 "secret\n", tlskey, ( ems ? "non-" : "" ) );
862 return -EPERM;
863 }
864
865 /* Pre-shared key must match schedule and digest */
866 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
867 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
868 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
869 ( psk->digest ? psk->digest->name : "(unknown)" ) );
870 return -EPERM;
871 }
872
873 /* Load key material */
874 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
875 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
876 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
877 return rc;
878
879 /* Set flags */
880 tlskey->kdf.flags = ( psk->flags & op->mask );
881
882 return 0;
883}
#define EPERM
Operation not permitted.
Definition errno.h:658

References DBGC, DBGC_HDA, tls_key_schedule::digest, tls_preshared_key::digest, ENOTTY, EPERM, EPROTO, tls_kdf_secret::flags, tls_preshared_key::flags, tls_key_schedule::kdf, tls_preshared_key::key, digest_algorithm::name, tls_key_schedule_operations::name, op, tls_key_schedule::op, tls_preshared_key::op, rc, TLSKEY_KDF_EMS, TLSKEY_KDF_MASTER, and tlskey_reset().

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), and tls_channel_load().

◆ tlskey_bind()

int tlskey_bind ( const struct tls_preshared_key * psk,
const void * prefix,
size_t prefix_len,
void * binder,
size_t binder_len )

Generate pre-shared key binder value.

Parameters
pskPre-shared key
prefixClientHello prefix
prefix_lenLength of ClientHello prefix
binderBinder value to fill in
binder_lenLength of binder value
Return values
rcReturn status code

Definition at line 895 of file tlskey.c.

896 {
897 const struct tls_key_schedule_operations *op = psk->op;
898 struct digest_algorithm *digest = psk->digest;
899 int rc;
900
901 /* Generate prefix digest and binder value */
902 if ( op && digest ) {
903 size_t digestsize = digest->digestsize;
904 size_t ctxsize = digest->ctxsize;
907
908 /* Calculate prefix digest */
909 digest_init ( digest, ctx );
910 digest_update ( digest, ctx, prefix, prefix_len );
911 digest_final ( digest, ctx, out );
912
913 /* Generate binder value */
914 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
915 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
916 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
917 return rc;
918 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
919 DBGC_HDA ( psk, 0, binder, binder_len );
920
921 return 0;
922 }
923
924 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
925 return -ENOENT;
926}
#define ENOENT
No such file or directory.
Definition errno.h:558
char prefix[4]
Definition vmconsole.c:53

References ctx, digest_algorithm::ctxsize, DBGC, DBGC2, DBGC2_HDA, DBGC_HDA, tls_preshared_key::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, digestsize, ENOENT, tls_preshared_key::key, op, tls_preshared_key::op, out, prefix, and rc.

Referenced by rfc8448_resumed_test().

◆ tlskey_hkdf_secretsize()

size_t tlskey_hkdf_secretsize ( struct digest_algorithm * digest)
static

Calculate secret size.

Parameters
digestDigest algorithm
Return values
secretsizeSecret size, or zero if unsupported

Definition at line 941 of file tlskey.c.

941 {
942 size_t digestsize = digest->digestsize;
943
944 return ( digestsize * 3 /* KDF, client, and server secrets */ );
945}

References digest_algorithm::digestsize, and digestsize.

◆ tlskey_hkdf_expand()

void tlskey_hkdf_expand ( struct digest_algorithm * digest,
const void * secret,
const char * label,
const void * seed,
size_t seed_len,
void * out,
size_t out_len )
static

Expand key material.

Parameters
digestDigest algorithm
secretSecret
labelLabel string
seedSeed material
seed_lenLength of seed material
outOutput buffer
out_lenLength of output buffer

Definition at line 958 of file tlskey.c.

961 {
962 static const char prefix[6] = "tls13 ";
963 const void *context = seed;
964 size_t context_len = seed_len;
965 size_t prefix_len = sizeof ( prefix );
966 size_t label_len = strlen ( label );
967 struct {
969 uint8_t label_len;
970 char prefix[prefix_len];
971 char label[label_len];
972 uint8_t context_len;
973 uint8_t context[context_len];
974 } __attribute__ (( packed )) info;
975
976 /* Construct additional information */
977 info.len = htons ( out_len );
978 info.label_len = ( prefix_len + label_len );
979 memcpy ( info.prefix, prefix, prefix_len );
980 memcpy ( info.label, label, label_len );
981 info.context_len = context_len;
982 memcpy ( info.context, context, context_len );
983
984 /* Generate output using HKDF */
985 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
986}
u32 info
Definition ar9003_mac.h:0
unsigned short uint16_t
Definition stdint.h:11
void hkdf_expand(struct digest_algorithm *digest, const void *prk, const void *info, size_t info_len, void *out, size_t len)
Expand pseudorandom key.
Definition hkdf.c:95
#define htons(value)
Definition byteswap.h:136
#define __attribute__(x)
Definition compiler.h:10
size_t strlen(const char *src)
Get length of string.
Definition string.c:244

References __attribute__, hkdf_expand(), htons, info, len, memcpy(), out, prefix, and strlen().

Referenced by tlskey_hkdf_bind(), and tlskey_hkdf_finished().

◆ tlskey_hkdf_empty()

void tlskey_hkdf_empty ( struct digest_algorithm * digest,
void * empty )
static

Calculate empty digest value.

Parameters
digestDigest algorithm
emptyEmpty digest to fill in

Definition at line 994 of file tlskey.c.

995 {
996 size_t ctxsize = digest->ctxsize;
997 uint8_t ctx[ctxsize];
998
999 /* Calculate empty digest */
1000 digest_init ( digest, ctx );
1001 digest_final ( digest, ctx, empty );
1002}

References ctx, digest_algorithm::ctxsize, digest_final(), and digest_init().

Referenced by tlskey_hkdf_apply(), and tlskey_hkdf_bind().

◆ tlskey_hkdf_finished()

void tlskey_hkdf_finished ( struct digest_algorithm * digest,
const void * secret,
const void * hash,
void * out )
static

Calculate a finished MAC.

Parameters
digestDigest algorithm
secretSecret
hashMessage hash
outOutput buffer

Definition at line 1012 of file tlskey.c.

1014 {
1015 size_t digestsize = digest->digestsize;
1016 size_t hctxsize = hmac_ctxsize ( digest );
1017 struct {
1018 uint8_t hctx[hctxsize];
1020 } tmp;
1021
1022 /* Generate HMAC key */
1023 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1024 tmp.key, sizeof ( tmp.key ) );
1025
1026 /* Generate HMAC */
1027 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1028 hmac_update ( digest, tmp.hctx, hash, digestsize );
1029 hmac_final ( digest, tmp.hctx, out );
1030
1031 /* Clear temporary secrets */
1032 memset ( &tmp, 0, sizeof ( tmp ) );
1033}
pseudo_bit_t hash[0x00010]
Definition arbel.h:2
void hmac_init(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len)
Initialise HMAC.
Definition hmac.c:106
void hmac_final(struct digest_algorithm *digest, void *ctx, void *hmac)
Finalise HMAC.
Definition hmac.c:124
static void hmac_update(struct digest_algorithm *digest, void *ctx, const void *data, size_t len)
Update HMAC.
Definition hmac.h:62
static size_t hmac_ctxsize(struct digest_algorithm *digest)
Calculate HMAC context size.
Definition hmac.h:48
static void tlskey_hkdf_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:958

References digest_algorithm::digestsize, digestsize, hash, hmac_ctxsize(), hmac_final(), hmac_init(), hmac_update(), key, memset(), NULL, out, tlskey_hkdf_expand(), and tmp.

Referenced by tlskey_hkdf_bind(), and tlskey_hkdf_verify().

◆ tlskey_hkdf_reset()

void tlskey_hkdf_reset ( struct tls_key_schedule * tlskey)
static

Reset key schedule.

Parameters
keyKey schedule

Definition at line 1040 of file tlskey.c.

1040 {
1041 struct digest_algorithm *digest = tlskey->digest;
1042 size_t digestsize = digest->digestsize;
1043 void *secret = tlskey->secret;
1044
1045 /* Allocate and initialise secrets */
1046 tlskey->kdf.secret = secret; secret += digestsize;
1047 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1048 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1049 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1050
1051 /* Initialise empty early secret */
1052 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1053 tlskey->kdf.secret );
1054}
void hkdf_extract(struct digest_algorithm *digest, const void *salt, size_t salt_len, const void *ikm, size_t ikm_len, void *prk)
Extract fixed-length pseudorandom key.
Definition hkdf.c:56
void * secret
Secret.
Definition tlskey.h:77
void * secret
Secret.
Definition tlskey.h:94

References assert, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, hkdf_extract(), tls_key_schedule::kdf, NULL, tls_kdf_secret::secret, tls_key_schedule::secret, tls_traffic_secret::secret, tls_key_schedule::secretsize, TLS_CLIENT, TLS_SERVER, and tls_key_schedule::traffic.

◆ tlskey_hkdf_apply()

int tlskey_hkdf_apply ( struct tls_key_schedule * tlskey,
const void * shared,
size_t shared_len )
static

Apply a new shared secret.

Parameters
tlskeyKey schedule
sharedNew shared secret
shared_lenLength of new shared secret
Return values
rcReturn status code

Definition at line 1064 of file tlskey.c.

1065 {
1066 struct digest_algorithm *digest = tlskey->digest;
1067 size_t digestsize = digest->digestsize;
1068 uint8_t empty[digestsize];
1069
1070 /* Generate derived secret */
1071 tlskey_hkdf_empty ( digest, empty );
1072 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1073 digestsize, tlskey->kdf.secret, digestsize );
1074 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1075 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1076
1077 /* Extract new pseudorandom key */
1078 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1079 shared_len, tlskey->kdf.secret );
1080 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1081 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1082
1083 return 0;
1084}
static void tlskey_hkdf_empty(struct digest_algorithm *digest, void *empty)
Calculate empty digest value.
Definition tlskey.c:994
static void tlskey_expand(struct tls_key_schedule *tlskey, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:466

References DBGC2, DBGC2_HDA, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, hkdf_extract(), tls_key_schedule::kdf, tls_kdf_secret::secret, tlskey_expand(), and tlskey_hkdf_empty().

◆ tlskey_hkdf_master()

int tlskey_hkdf_master ( struct tls_key_schedule * tlskey,
int ems )
static

Generate master secret.

Parameters
tlskeyKey schedule
emsExtended master secret extension is enabled
Return values
rcReturn status code

Definition at line 1093 of file tlskey.c.

1093 {
1094 struct digest_algorithm *digest = tlskey->digest;
1095 size_t digestsize = digest->digestsize;
1096 uint8_t zero[digestsize];
1097 int rc;
1098
1099 /* Extended master secret must always be used */
1100 if ( ! ems ) {
1101 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1102 "secret\n", tlskey );
1103 return -EPROTO;
1104 }
1105
1106 /* Generate master secret */
1107 memset ( zero, 0, sizeof ( zero ) );
1108 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1109 return rc;
1110
1111 return 0;
1112}
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:522

References DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, EPROTO, memset(), rc, and tlskey_apply().

◆ tlskey_hkdf_verify()

int tlskey_hkdf_verify ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
void * verify,
size_t verify_len )
static

Generate verification data.

Parameters
tlskeyKey schedule
endVerification endpoint
verifyVerification data to fill in
verify_lenLength of verification data
Return values
rcReturn status code

Definition at line 1123 of file tlskey.c.

1125 {
1126 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1127 struct digest_algorithm *digest = tlskey->digest;
1128 size_t digestsize = digest->digestsize;
1129
1130 /* Verification data must be a complete digest output */
1131 if ( verify_len != digestsize )
1132 return -EINVAL;
1133
1134 /* Verification data is derived from handshake secrets */
1135 if ( traffic->phase != &tls_handshake ) {
1136 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1137 "data without %s handshake traffic secrets\n",
1138 tlskey, end->name, end->name );
1139 return -EPROTO;
1140 }
1141
1142 /* Generate verification data */
1143 tlskey_hkdf_finished ( digest, traffic->secret,
1144 tlskey->transcript.running, verify );
1145 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1146 DBGC_HDA ( tlskey, 0, verify, verify_len );
1147
1148 return 0;
1149}
#define EINVAL
Invalid argument.
Definition errno.h:472
const struct tls_phase tls_handshake
Handshake traffic phase.
Definition tlskey.c:144
static void tlskey_hkdf_finished(struct digest_algorithm *digest, const void *secret, const void *hash, void *out)
Calculate a finished MAC.
Definition tlskey.c:1012

References DBGC, DBGC_HDA, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, EINVAL, end, EPROTO, tls_traffic_secret::phase, tls_transcript::running, tls_traffic_secret::secret, tls_handshake, tlskey_hkdf_finished(), tls_key_schedule::traffic, and tls_key_schedule::transcript.

◆ tlskey_hkdf_traffic()

int tlskey_hkdf_traffic ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
const struct tls_phase * phase )
static

Generate traffic secret.

Parameters
tlskeyKey schedule
writerWriter endpoint
phaseTraffic phase
Return values
rcReturn status code

Definition at line 1159 of file tlskey.c.

1161 {
1162 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1163 struct digest_algorithm *digest = tlskey->digest;
1164 size_t digestsize = digest->digestsize;
1165 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1166
1167 /* Generate label */
1168 snprintf ( label, sizeof ( label ), "%c %s traffic",
1169 writer->name[0], phase->label );
1170
1171 /* Generate traffic secret */
1172 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1174 traffic->secret, digestsize );
1175
1176 return 0;
1177}
const char label[3]
Key expansion label.
Definition tlskey.c:131
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, tls_transcript::finishing, tls_endpoint::index, tls_key_schedule::kdf, tls_phase::label, tls_endpoint::name, tls_kdf_secret::secret, tls_traffic_secret::secret, snprintf(), tlskey_expand(), tls_key_schedule::traffic, and tls_key_schedule::transcript.

◆ tlskey_hkdf_cipher()

int tlskey_hkdf_cipher ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
void * key,
size_t key_len,
void * iv,
size_t iv_len,
void *mac __unused,
size_t mac_len )
static

Generate cipher key material.

Parameters
tlskeyKey schedule
writerWriter endpoint
keyCipher key to fill in
key_lenLength of cipher key
ivFixed portion of initialisation vector to fill in
iv_lenLength of fixed portion of initialisation vector
macMAC secret to fill in
mac_lenLength of MAC secret
Return values
rcReturn status code

Definition at line 1192 of file tlskey.c.

1196 {
1197 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1198 struct digest_algorithm *digest = tlskey->digest;
1199 size_t digestsize = digest->digestsize;
1200 void *secret = traffic->secret;
1201
1202 /* The key schedule does not define a way to generate MAC secrets */
1203 if ( mac_len ) {
1204 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1205 tlskey );
1206 return -ENOTSUP;
1207 }
1208
1209 /* Generate cipher key */
1210 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1211
1212 /* Generate initialisation vector */
1213 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1214
1215 /* Update traffic secret, if applicable */
1216 if ( traffic->phase == &tls_application ) {
1217 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1218 secret, digestsize );
1219 }
1220
1221 return 0;
1222}
const struct tls_phase tls_application
Application traffic phase.
Definition tlskey.c:151

References __unused, DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, ENOTSUP, tls_endpoint::index, iv, key, mac, NULL, tls_traffic_secret::phase, tls_traffic_secret::secret, tls_application, tlskey_expand(), and tls_key_schedule::traffic.

◆ tlskey_hkdf_tbshash()

int tlskey_hkdf_tbshash ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
struct digest_algorithm * digest,
const void *data __unused,
size_t len,
void * tbs )
static

Generate signable digest value.

Parameters
tlskeyKey schedule
endEndpoint
digestSignature digest algorithm
dataAdditional data
lenLength of additional data
tbsSignable digest value to fill in
Return values
rcReturn status code

Definition at line 1235 of file tlskey.c.

1239 {
1240 size_t ctxsize = digest->ctxsize;
1241 uint8_t ctx[ctxsize];
1242 char buf[64];
1243 int label_len;
1244
1245 /* There is no way to incorporate additional data */
1246 if ( len ) {
1247 DBGC ( tlskey, "TLSKEY %p cannot generate digest with "
1248 "additional data\n", tlskey );
1249 return -ENOTSUP;
1250 }
1251
1252 /* Generate digest value (all input is public) */
1253 digest_init ( digest, ctx );
1254 memset ( buf, 0x20, sizeof ( buf ) );
1255 digest_update ( digest, ctx, buf, sizeof ( buf ) );
1256 label_len = snprintf ( buf, sizeof ( buf ),
1257 "TLS 1.3, %s CertificateVerify", end->name );
1258 assert ( label_len == 33 /* for both "client" and "server" */ );
1259 digest_update ( digest, ctx, buf, ( label_len + 1 /* NUL */ ) );
1260 digest_update ( digest, ctx, tlskey->transcript.running,
1261 tlskey->digest->digestsize );
1262 digest_final ( digest, ctx, tbs );
1263
1264 return 0;
1265}

References __unused, assert, ctx, digest_algorithm::ctxsize, data, DBGC, tls_key_schedule::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, end, ENOTSUP, len, memset(), tls_transcript::running, snprintf(), and tls_key_schedule::transcript.

◆ tlskey_hkdf_save()

int tlskey_hkdf_save ( struct tls_key_schedule * tlskey,
const void * nonce,
size_t nonce_len,
struct tls_preshared_key * psk )
static

Save pre-shared key.

Parameters
tlskeyKey schedule
nonceTicket nonce
nonce_lenLength of ticket nonce
pskPre-shared key to fill in
Return values
rcReturn status code

Definition at line 1276 of file tlskey.c.

1278 {
1279 struct digest_algorithm *digest = tlskey->digest;
1280 size_t digestsize = digest->digestsize;
1281 struct {
1282 uint8_t master[digestsize];
1283 } tmp;
1284
1285 /* The pre-shared key currently uses a fixed-size buffer */
1286 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1287 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1288 tlskey, digest->name );
1289 return -ENOTSUP;
1290 }
1291
1292 /* Generate resumption master secret */
1293 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1295 tmp.master, sizeof ( tmp.master ) );
1296
1297 /* Generate resumption secret */
1298 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1299 psk->key.resumption, digestsize );
1300
1301 /* Clear temporary secrets */
1302 memset ( &tmp, 0, sizeof ( tmp ) );
1303
1304 return 0;
1305}
uint8_t resumption[48]
Resumption secret.
Definition tlskey.h:165

References DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, ENOTSUP, tls_transcript::finishing, tls_key_schedule::kdf, tls_preshared_key::key, memset(), digest_algorithm::name, nonce, tls_preshared_key::resumption, tls_kdf_secret::secret, tlskey_expand(), tmp, and tls_key_schedule::transcript.

◆ tlskey_hkdf_load()

int tlskey_hkdf_load ( struct tls_key_schedule * tlskey,
const struct tls_preshared_key * psk )
static

Load pre-shared key.

Parameters
tlskeyKey schedule
pskPre-shared key
Return values
rcReturn status code

Definition at line 1314 of file tlskey.c.

1315 {
1316 struct digest_algorithm *digest = tlskey->digest;
1317 size_t digestsize = digest->digestsize;
1318
1319 /* Sanity checks */
1320 assert ( digest == psk->digest );
1321 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1322
1323 /* Extract early secret */
1324 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1325 tlskey->kdf.secret );
1326 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1327 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1328
1329 return 0;
1330}

References assert, DBGC2, DBGC2_HDA, tls_key_schedule::digest, tls_preshared_key::digest, digest_algorithm::digestsize, digestsize, hkdf_extract(), tls_key_schedule::kdf, tls_preshared_key::key, NULL, tls_preshared_key::resumption, and tls_kdf_secret::secret.

◆ tlskey_hkdf_bind()

int tlskey_hkdf_bind ( const struct tls_preshared_key * psk,
const void * hash,
void * binder,
size_t binder_len )
static

Generate pre-shared key binder value.

Parameters
pskPre-shared key
hashPartial transcript hash
binderBinder value to fill in
binder_lenLength of binder value
Return values
rcReturn status code

Definition at line 1341 of file tlskey.c.

1343 {
1344 struct digest_algorithm *digest = psk->digest;
1345 size_t digestsize = digest->digestsize;
1346 uint8_t empty[digestsize];
1347 struct {
1349 } tmp;
1350
1351 /* Binder value must be a complete digest output */
1352 if ( binder_len != digestsize )
1353 return -EINVAL;
1354
1355 /* Extract temporary copy of early secret */
1356 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize, tmp.key );
1357 DBGC2 ( psk, "TLSKEY %p temporary early secret:\n", psk );
1358 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1359
1360 /* Generate resumption binder secret */
1361 tlskey_hkdf_empty ( digest, empty );
1362 tlskey_hkdf_expand ( digest, tmp.key, "res binder", empty, digestsize,
1363 tmp.key, digestsize );
1364 DBGC2 ( psk, "TLSKEY %p resumption binder secret:\n", psk );
1365 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1366
1367 /* Generate binder */
1368 tlskey_hkdf_finished ( digest, tmp.key, hash, binder );
1369 DBGC2 ( psk, "TLSKEY %p binder:\n", psk );
1370 DBGC2_HDA ( psk, 0, binder, binder_len );
1371
1372 /* Clear temporary secrets */
1373 memset ( &tmp, 0, sizeof ( tmp ) );
1374
1375 return 0;
1376}

References DBGC2, DBGC2_HDA, tls_preshared_key::digest, digest_algorithm::digestsize, digestsize, EINVAL, hash, hkdf_extract(), key, tls_preshared_key::key, memset(), NULL, tlskey_hkdf_empty(), tlskey_hkdf_expand(), tlskey_hkdf_finished(), and tmp.

◆ tlskey_hash_secretsize()

size_t tlskey_hash_secretsize ( struct digest_algorithm * digest)
static

Calculate secret size.

Parameters
digestDigest algorithm
Return values
secretsizeSecret size, or zero if unsupported

Definition at line 1413 of file tlskey.c.

1413 {
1414
1415 /* A P_Hash() key is an HMAC key */
1416 return hmac_keysize ( digest );
1417}
static size_t hmac_keysize(struct digest_algorithm *digest)
Calculate HMAC reduced key size.
Definition hmac.h:35

References hmac_keysize().

◆ tlskey_hash_expand()

void tlskey_hash_expand ( struct digest_algorithm * digest,
const void * secret,
const char * label,
const void * seed,
size_t seed_len,
void * out,
size_t out_len )
static

Expand key material.

Parameters
digestDigest algorithm
secretSecret
labelLabel string
seedSeed material
seed_lenLength of seed material
outOutput buffer
out_lenLength of output buffer

Definition at line 1430 of file tlskey.c.

1433 {
1434 size_t digestsize = digest->digestsize;
1435 size_t hctxsize = hmac_ctxsize ( digest );
1436 size_t frag_len = digestsize;
1437 size_t label_len = strlen ( label );
1438 unsigned int index = 0;
1439 struct {
1440 uint8_t ctx[2][hctxsize];
1442 uint8_t frag[digestsize];
1443 } tmp;
1444
1445 /* Generate as much output as required */
1446 while ( out_len ) {
1447
1448 /* Generate A(n) and output fragment */
1449 hmac_init_key ( digest, tmp.ctx[0], secret );
1450 if ( index ) {
1451 hmac_update ( digest, tmp.ctx[0], tmp.a,
1452 sizeof ( tmp.a ) );
1453 memcpy ( tmp.ctx[1], tmp.ctx[0],
1454 sizeof ( tmp.ctx[1] ) );
1455 }
1456 hmac_update ( digest, tmp.ctx[0], label, label_len );
1457 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1458 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1459 if ( index++ == 0 )
1460 continue;
1461 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1462
1463 /* Copy output */
1464 if ( frag_len > out_len )
1465 frag_len = out_len;
1466 memcpy ( out, tmp.frag, frag_len );
1467
1468 /* Move to next fragment */
1469 out += frag_len;
1470 out_len -= frag_len;
1471 }
1472
1473 /* Clear temporary secrets */
1474 memset ( &tmp, 0, sizeof ( tmp ) );
1475}
void hmac_init_key(struct digest_algorithm *digest, void *ctx, const void *key)
Initialise HMAC from reduced key.
Definition hmac.c:82

References ctx, digest_algorithm::digestsize, digestsize, hmac_ctxsize(), hmac_final(), hmac_init_key(), hmac_update(), index, memcpy(), memset(), out, strlen(), and tmp.

Referenced by tlskey_md5_sha1_expand().

◆ tlskey_hash_reset()

void tlskey_hash_reset ( struct tls_key_schedule * tlskey)
static

Reset key schedule.

Parameters
keyKey schedule

Definition at line 1482 of file tlskey.c.

1482 {
1483 void *secret = tlskey->secret;
1484
1485 /* Allocate and initialise secrets */
1486 tlskey->kdf.secret = secret;
1487 tlskey->traffic[TLS_CLIENT].secret = secret;
1488 tlskey->traffic[TLS_SERVER].secret = secret;
1489}

References tls_key_schedule::kdf, tls_kdf_secret::secret, tls_key_schedule::secret, tls_traffic_secret::secret, TLS_CLIENT, TLS_SERVER, and tls_key_schedule::traffic.

◆ tlskey_hash_apply()

int tlskey_hash_apply ( struct tls_key_schedule * tlskey,
const void * shared,
size_t shared_len )
static

Apply a new shared secret.

Parameters
tlskeyKey schedule
sharedNew shared secret
shared_lenLength of new shared secret
Return values
rcReturn status code

Definition at line 1499 of file tlskey.c.

1500 {
1501 struct digest_algorithm *digest = tlskey->digest;
1502 size_t hctxsize = hmac_ctxsize ( digest );
1503 struct {
1504 uint8_t hctx[hctxsize];
1505 } tmp;
1506
1507 /* Set HMAC key */
1508 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1509
1510 /* Clear temporary secrets */
1511 memset ( &tmp, 0, sizeof ( tmp ) );
1512
1513 return 0;
1514}
void hmac_key(struct digest_algorithm *digest, void *ctx, const void *secret, size_t len, void *key)
Construct HMAC reduced key.
Definition hmac.c:59

References tls_key_schedule::digest, hmac_ctxsize(), hmac_key(), tls_key_schedule::kdf, memset(), tls_kdf_secret::secret, and tmp.

◆ tlskey_hash_master()

int tlskey_hash_master ( struct tls_key_schedule * tlskey,
int ems )
static

Generate master secret.

Parameters
tlskeyKey schedule
emsExtended master secret extension is enabled
Return values
rcReturn status code

Definition at line 1523 of file tlskey.c.

1523 {
1524 struct digest_algorithm *digest = tlskey->digest;
1525 size_t digestsize = digest->digestsize;
1526 const char *label;
1527 const void *seed;
1528 size_t seed_len;
1529 struct {
1530 uint8_t master[48];
1531 } tmp;
1532 int rc;
1533
1534 /* Master secret is derived from the client and server random
1535 * values (or the full transcript digest).
1536 */
1537 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
1538 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
1539 "without a digested nonce\n", tlskey );
1540 return -EPROTO;
1541 }
1542
1543 /* Generate master secret */
1544 if ( ems ) {
1545 label = "extended master secret";
1546 seed = tlskey->transcript.running;
1547 seed_len = digestsize;
1548 } else {
1549 label = "master secret";
1550 seed = &tlskey->random;
1551 seed_len = sizeof ( tlskey->random );
1552 }
1553 tlskey_expand ( tlskey, tlskey->kdf.secret, label, seed, seed_len,
1554 tmp.master, sizeof ( tmp.master ) );
1555
1556 /* Apply master secret */
1557 if ( ( rc = tlskey_apply ( tlskey, tmp.master,
1558 sizeof ( tmp.master ) ) ) != 0 ) {
1559 goto err_apply;
1560 }
1561
1562 err_apply:
1563 memset ( &tmp, 0, sizeof ( tmp ) );
1564 return rc;
1565}

References DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, EPROTO, tls_transcript::flags, tls_key_schedule::kdf, memset(), tls_key_schedule::random, rc, tls_transcript::running, tls_kdf_secret::secret, tlskey_apply(), tlskey_expand(), TLSKEY_TSF_NONCED, tmp, and tls_key_schedule::transcript.

◆ tlskey_hash_verify()

int tlskey_hash_verify ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
void * verify,
size_t verify_len )
static

Generate verification data.

Parameters
tlskeyKey schedule
endVerification endpoint
verifyVerification data to fill in
verify_lenLength of verification data
Return values
rcReturn status code

Definition at line 1576 of file tlskey.c.

1578 {
1579 struct digest_algorithm *digest = tlskey->digest;
1580 size_t digestsize = digest->digestsize;
1581 char label[ 16 /* "[client|server] finished" + NUL */ ];
1582
1583 /* Verification data must be at least 12 bytes for all digests */
1584 if ( verify_len < TLSKEY_HASH_VERIFY_MIN )
1585 return -EINVAL;
1586
1587 /* Verification data is derived from the master secret */
1588 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
1589 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
1590 "without a master secret\n", tlskey );
1591 return -EPROTO;
1592 }
1593
1594 /* Construct label */
1595 snprintf ( label, sizeof ( label ), "%s finished", end->name );
1596
1597 /* Generate verification data */
1598 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1599 tlskey->transcript.running, digestsize,
1600 verify, verify_len );
1601
1602 return 0;
1603}
#define TLSKEY_HASH_VERIFY_MIN
Minimum length for verification data.
Definition tlskey.c:1405

References DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, digestsize, EINVAL, end, EPROTO, tls_kdf_secret::flags, tls_key_schedule::kdf, tls_transcript::running, tls_kdf_secret::secret, snprintf(), tlskey_expand(), TLSKEY_HASH_VERIFY_MIN, TLSKEY_KDF_MASTER, and tls_key_schedule::transcript.

◆ tlskey_hash_traffic()

int tlskey_hash_traffic ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
const struct tls_phase * phase )
static

Generate traffic secret.

Parameters
tlskeyKey schedule
writerWriter endpoint
phaseTraffic phase
Return values
rcReturn status code

Definition at line 1613 of file tlskey.c.

1615 {
1616 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1617
1618 /* Only application phase keys are supported */
1619 if ( phase != &tls_application ) {
1620 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1621 tlskey, phase->name );
1622 return -ENOTSUP;
1623 }
1624
1625 /* There are no separate traffic secrets */
1626 assert ( traffic->secret == tlskey->kdf.secret );
1627
1628 return 0;
1629}

References assert, DBGC, ENOTSUP, tls_endpoint::index, tls_key_schedule::kdf, tls_phase::name, tls_traffic_secret::phase, tls_kdf_secret::secret, tls_traffic_secret::secret, tls_application, and tls_key_schedule::traffic.

◆ tlskey_hash_cipher()

int tlskey_hash_cipher ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * writer,
void * key,
size_t key_len,
void * iv,
size_t iv_len,
void * mac,
size_t mac_len )
static

Generate cipher key material.

Parameters
tlskeyKey schedule
writerWriter endpoint
keyCipher key to fill in
key_lenLength of cipher key
ivFixed portion of initialisation vector to fill in
iv_lenLength of fixed portion of initialisation vector
macMAC secret to fill in
mac_lenLength of MAC secret
Return values
rcReturn status code

Definition at line 1644 of file tlskey.c.

1647 {
1648 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1649 struct {
1650 uint8_t key[total];
1651 } tmp;
1652 struct {
1653 struct tls_random server;
1654 struct tls_random client;
1655 } __attribute__ (( packed )) seed;
1656 const void *src;
1657 size_t mask;
1658
1659 /* Construct seed (with swapped client/server random bytes) */
1660 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1661 sizeof ( seed.server ) );
1662 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1663 sizeof ( seed.client ) );
1664
1665 /* Generate key material */
1666 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1667 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1668
1669 /* Partition key material */
1670 src = tmp.key;
1671 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1672 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1673 src += ( 2 * mac_len );
1674 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1675 src += ( 2 * key_len );
1676 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1677 src += ( 2 * iv_len );
1678 assert ( src == &tmp.key[total] );
1679
1680 /* Clear temporary secrets */
1681 memset ( &tmp, 0, sizeof ( tmp ) );
1682
1683 return 0;
1684}
static const void * src
Definition string.h:48

References __attribute__, assert, tls_endpoint::index, iv, tls_key_schedule::kdf, key, mac, memcpy(), memset(), tls_key_schedule::random, tls_kdf_secret::secret, src, TLS_CLIENT, TLS_SERVER, tlskey_expand(), and tmp.

◆ tlskey_hash_tbshash()

int tlskey_hash_tbshash ( struct tls_key_schedule * tlskey,
const struct tls_endpoint * end,
struct digest_algorithm * digest,
const void * data,
size_t len,
void * tbs )
static

Generate signable digest value.

Parameters
tlskeyKey schedule
endEndpoint
digestSignature digest algorithm
dataAdditional data
lenLength of additional data
tbsSignable digest value to fill in
Return values
rcReturn status code

Definition at line 1697 of file tlskey.c.

1700 {
1701 size_t ctxsize = digest->ctxsize;
1702 struct {
1703 uint8_t ctx[ctxsize];
1704 } tmp;
1705
1706 /* Generate endpoint-specific digest value */
1707 if ( end->index == TLS_CLIENT ) {
1708
1709 /* The client CertificateVerify digest value is the
1710 * raw transcript digest. We retain only a single
1711 * running transcript digest, and can therefore
1712 * provide this only for a digest algorithm that
1713 * matches our transcript digest algorithm.
1714 */
1715 if ( digest != tlskey->digest ) {
1716 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1717 "transcript digest\n", tlskey, digest->name );
1718 return -ENOTSUP;
1719 }
1720
1721 /* There is no way to incorporate additional data */
1722 if ( len ) {
1723 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1724 "with additional data\n", tlskey );
1725 return -ENOTSUP;
1726 }
1727
1728 /* Copy transcript digest value */
1729 memcpy ( tbs, tlskey->transcript.running,
1730 digest->digestsize );
1731
1732 } else {
1733
1734 /* Additional data (i.e. the ServerKeyExchange
1735 * parameters) must be incorporated, since otherwise
1736 * the digest does not cover the parameters used to
1737 * establish the shared secret.
1738 */
1739 if ( ! len ) {
1740 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1741 "without additional data\n", tlskey );
1742 return -ENOTSUP;
1743 }
1744
1745 /* Generate ServerKeyExchange digest */
1746 digest_init ( digest, tmp.ctx );
1747 digest_update ( digest, tmp.ctx, &tlskey->random,
1748 sizeof ( tlskey->random ) );
1749 digest_update ( digest, tmp.ctx, data, len );
1750 digest_final ( digest, tmp.ctx, tbs );
1751 }
1752
1753 /* Clear temporary secrets */
1754 memset ( &tmp, 0, sizeof ( tmp ) );
1755
1756 return 0;
1757}

References ctx, digest_algorithm::ctxsize, data, DBGC, tls_key_schedule::digest, digest_final(), digest_init(), digest_update(), digest_algorithm::digestsize, end, ENOTSUP, len, memcpy(), memset(), digest_algorithm::name, tls_key_schedule::random, tls_transcript::running, TLS_CLIENT, tmp, and tls_key_schedule::transcript.

◆ tlskey_hash_save()

int tlskey_hash_save ( struct tls_key_schedule * tlskey,
const void *nonce __unused,
size_t nonce_len,
struct tls_preshared_key * psk )
static

Save pre-shared key.

Parameters
tlskeyKey schedule
nonceTicket nonce
nonce_lenLength of ticket nonce
pskPre-shared key to fill in
Return values
rcReturn status code

Definition at line 1768 of file tlskey.c.

1770 {
1771 struct digest_algorithm *digest = tlskey->digest;
1772
1773 /* A ticket nonce is not supported */
1774 if ( nonce_len )
1775 return -ENOTSUP;
1776
1777 /* For TLS version 1.2, the pre-master secret may be any
1778 * length but the master secret is fixed at 48 bytes. This is
1779 * smaller than the block size for all supported digest
1780 * algorithms. The HMAC key constructed from the master
1781 * secret will therefore be just the zero-padded master secret
1782 * value. We can therefore preserve just these first 48 bytes
1783 * of the KDF master secret (ignoring the zero padding up to
1784 * the digest block size).
1785 */
1786 assert ( sizeof ( psk->key.master_secret ) <=
1787 hmac_keysize ( digest ) );
1788 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1789 sizeof ( psk->key.master_secret ) );
1790
1791 return 0;
1792}
union tls_preshared_key::@022173016027117201055347232316162256252261104170::@216204225163015142232067115177347130257031275370 master_secret
Master secret.

References __unused, assert, tls_key_schedule::digest, ENOTSUP, hmac_keysize(), tls_key_schedule::kdf, tls_preshared_key::key, tls_preshared_key::master_secret, memcpy(), nonce, and tls_kdf_secret::secret.

◆ tlskey_hash_load()

int tlskey_hash_load ( struct tls_key_schedule * tlskey,
const struct tls_preshared_key * psk )
static

Load pre-shared key.

Parameters
tlskeyKey schedule
pskPre-shared key
Return values
rcReturn status code

Definition at line 1801 of file tlskey.c.

1802 {
1803 const void *secret;
1804 size_t secret_len;
1805 int rc;
1806
1807 /* For TLS versions 1.2 and earlier, the pre-shared key
1808 * material contains the master secret and so we just apply
1809 * this as the key derivation function secret.
1810 */
1811 secret = &psk->key.master_secret;
1812 secret_len = sizeof ( psk->key.master_secret );
1813 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1814 return rc;
1815
1816 return 0;
1817}

References tls_preshared_key::key, tls_preshared_key::master_secret, rc, and tlskey_apply().

◆ tlskey_hash_bind()

int tlskey_hash_bind ( const struct tls_preshared_key *psk __unused,
const void *hash __unused,
void *binder __unused,
size_t binder_len )
static

Generate pre-shared key binder value.

Parameters
pskPre-shared key
hashPartial transcript hash
binderBinder value to fill in
binder_lenLength of binder value
Return values
rcReturn status code

Definition at line 1828 of file tlskey.c.

1830 {
1831
1832 /* Binder values are not supported */
1833 if ( binder_len )
1834 return -ENOTSUP;
1835
1836 return 0;
1837}

References __unused, ENOTSUP, and hash.

◆ tlskey_md5_sha1_secretsize()

size_t tlskey_md5_sha1_secretsize ( struct digest_algorithm * digest)
static

Calculate secret size.

Parameters
digestDigest algorithm
Return values
secretsizeSecret size, or zero if unsupported

Definition at line 1871 of file tlskey.c.

1871 {
1872 struct md5_sha1_hmac_keys *hkeys;
1873 size_t secretsize;
1874
1875 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1876 if ( digest != &md5_sha1_algorithm )
1877 return 0;
1878
1879 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1880 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1881 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1882 secretsize = sizeof ( *hkeys );
1883
1884 return secretsize;
1885}
struct digest_algorithm md5_algorithm
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:87
struct digest_algorithm sha1_algorithm
An MD5+SHA1 HMAC key block.
Definition md5_sha1.h:57
uint8_t md5[MD5_BLOCK_SIZE]
MD5 HMAC key.
Definition md5_sha1.h:59
uint8_t sha1[SHA1_BLOCK_SIZE]
SHA-1 HMAC key.
Definition md5_sha1.h:61

References assert, hmac_keysize(), md5_sha1_hmac_keys::md5, md5_algorithm, md5_sha1_algorithm, md5_sha1_hmac_keys::sha1, and sha1_algorithm.

◆ tlskey_md5_sha1_expand()

void tlskey_md5_sha1_expand ( struct digest_algorithm * digest,
const void * secret,
const char * label,
const void * seed,
size_t seed_len,
void * out,
size_t out_len )
static

Expand key material.

Parameters
digestDigest algorithm
secretSecret
labelLabel string
seedSeed material
seed_lenLength of seed material
outOutput buffer
out_lenLength of output buffer

Definition at line 1898 of file tlskey.c.

1901 {
1902 const struct md5_sha1_hmac_keys *hkeys = secret;
1903 struct {
1904 uint8_t sha1[out_len];
1905 } tmp;
1906 uint8_t *xor;
1907 unsigned int i;
1908
1909 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1910 assert ( digest == &md5_sha1_algorithm );
1911
1912 /* Generate MD5 portion into output buffer */
1913 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1914 seed_len, out, out_len );
1915
1916 /* Generate SHA-1 portion into temporary buffer */
1917 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1918 seed_len, tmp.sha1, out_len );
1919
1920 /* XOR together into output buffer */
1921 xor = out;
1922 for ( i = 0 ; i < out_len ; i++ )
1923 xor[i] ^= tmp.sha1[i];
1924
1925 /* Clear temporary secrets */
1926 memset ( &tmp, 0, sizeof ( tmp ) );
1927}
static u32 xor(u32 a, u32 b)
Definition tlan.h:457
static void tlskey_hash_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:1430

References assert, md5_sha1_hmac_keys::md5, md5_algorithm, md5_sha1_algorithm, memset(), out, md5_sha1_hmac_keys::sha1, sha1_algorithm, tlskey_hash_expand(), tmp, and xor().

◆ tlskey_md5_sha1_apply()

int tlskey_md5_sha1_apply ( struct tls_key_schedule * tlskey,
const void * shared,
size_t shared_len )
static

Apply a new shared secret.

Parameters
tlskeyKey schedule
sharedNew shared secret
shared_lenLength of new shared secret
Return values
rcReturn status code

Definition at line 1937 of file tlskey.c.

1938 {
1939 struct digest_algorithm *digest = tlskey->digest;
1940 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1941 size_t hctxsize = hmac_ctxsize ( digest );
1942 struct {
1943 uint8_t hctx[hctxsize];
1944 } tmp;
1945 const void *shared_md5;
1946 const void *shared_sha1;
1947 size_t shared_sublen;
1948
1949 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1950 assert ( digest == &md5_sha1_algorithm );
1951
1952 /* Split secret into two, with an overlap of up to one byte */
1953 shared_sublen = ( ( shared_len + 1 ) / 2 );
1954 shared_md5 = shared;
1955 shared_sha1 = ( shared + shared_len - shared_sublen );
1956
1957 /* Set HMAC-MD5 key */
1958 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1959 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1960 hkeys->md5 );
1961
1962 /* Set HMAC-SHA1 key */
1963 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1964 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1965 hkeys->sha1 );
1966
1967 /* Clear temporary secrets */
1968 memset ( &tmp, 0, sizeof ( tmp ) );
1969
1970 return 0;
1971}

References assert, tls_key_schedule::digest, hmac_ctxsize(), hmac_key(), tls_key_schedule::kdf, md5_sha1_hmac_keys::md5, md5_algorithm, md5_sha1_algorithm, memset(), tls_kdf_secret::secret, md5_sha1_hmac_keys::sha1, sha1_algorithm, and tmp.

◆ tlskey_md5_sha1_save()

int tlskey_md5_sha1_save ( struct tls_key_schedule * tlskey,
const void *nonce __unused,
size_t nonce_len,
struct tls_preshared_key * psk )
static

Save pre-shared key.

Parameters
tlskeyKey schedule
nonceTicket nonce
nonce_lenLength of ticket nonce
pskPre-shared key
Return values
rcReturn status code

Definition at line 1982 of file tlskey.c.

1985 {
1986 struct digest_algorithm *digest = tlskey->digest;
1987 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1988
1989 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1990 assert ( digest == &md5_sha1_algorithm );
1991
1992 /* A ticket nonce is not supported */
1993 if ( nonce_len )
1994 return -ENOTSUP;
1995
1996 /* For TLS versions 1.1 and earlier, the pre-master secret may
1997 * be any length but the master secret is fixed at 48 bytes.
1998 * It will have been split to become 24 bytes in each of the
1999 * MD5 and SHA-1 HMAC keys.
2000 */
2001 assert ( sizeof ( psk->key.master_secret.md5 ) <=
2003 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
2005 memcpy ( psk->key.master_secret.md5, hkeys->md5,
2006 sizeof ( psk->key.master_secret.md5 ) );
2007 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
2008 sizeof ( psk->key.master_secret.sha1 ) );
2009
2010 return 0;
2011}
uint8_t md5[24]
Definition tlskey.h:151
uint8_t sha1[24]
Definition tlskey.h:152

References __unused, assert, tls_key_schedule::digest, ENOTSUP, hmac_keysize(), tls_key_schedule::kdf, tls_preshared_key::key, tls_preshared_key::master_secret, md5_sha1_hmac_keys::md5, tls_preshared_key::md5, md5_algorithm, md5_sha1_algorithm, memcpy(), nonce, tls_kdf_secret::secret, md5_sha1_hmac_keys::sha1, tls_preshared_key::sha1, and sha1_algorithm.

Variable Documentation

◆ tls_client

const struct tls_endpoint tls_client
Initial value:
= {
.index = TLS_CLIENT,
.name = "client",
}

Client endpoint.

Definition at line 102 of file tlskey.c.

102 {
103 .index = TLS_CLIENT,
104 .name = "client",
105};

◆ tls_server

const struct tls_endpoint tls_server
Initial value:
= {
.index = TLS_SERVER,
.name = "server",
}

Server endpoint.

Definition at line 108 of file tlskey.c.

108 {
109 .index = TLS_SERVER,
110 .name = "server",
111};

◆ tls_endpoint

const struct tls_endpoint* tls_endpoint[]
static
Initial value:
= {
}
TLS client state.
Definition tls.h:451
TLS server state.
Definition tls.h:461

Endpoint list.

Definition at line 114 of file tlskey.c.

114 {
117};

◆ tls_early

const struct tls_phase tls_early
Initial value:
= {
.name = "early",
.label = "e",
.flags = TLSKEY_KDF_KEYED,
}

Early traffic phase.

Definition at line 137 of file tlskey.c.

137 {
138 .name = "early",
139 .label = "e",
140 .flags = TLSKEY_KDF_KEYED,
141};

Referenced by rfc8448_resumed_test().

◆ tls_handshake

const struct tls_phase tls_handshake
Initial value:
= {
.name = "handshake",
.label = "hs",
.flags = TLSKEY_KDF_KEYED,
}

Handshake traffic phase.

Definition at line 144 of file tlskey.c.

144 {
145 .name = "handshake",
146 .label = "hs",
147 .flags = TLSKEY_KDF_KEYED,
148};

Referenced by rfc8448_resumed_test(), rfc8448_simple_test(), tls_new_server_hello(), and tlskey_hkdf_verify().

◆ tls_application

const struct tls_phase tls_application
Initial value:
= {
.name = "application",
.label = "ap",
}

Application traffic phase.

Definition at line 151 of file tlskey.c.

151 {
152 .name = "application",
153 .label = "ap",
154 .flags = ( TLSKEY_KDF_KEYED | TLSKEY_KDF_MASTER ),
155};

Referenced by dummy_hash(), dummy_md5_sha1(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_new_change_cipher(), tls_new_finished(), tls_send_change_cipher(), tls_send_finished(), tlskey_hash_traffic(), and tlskey_hkdf_cipher().

◆ tlskey_hkdf

const struct tls_key_schedule_operations tlskey_hkdf
Initial value:
= {
.name = "HKDF",
.accumulates = 1,
.secretsize = tlskey_hkdf_secretsize,
.expand = tlskey_hkdf_expand,
.master = tlskey_hkdf_master,
.verify = tlskey_hkdf_verify,
.traffic = tlskey_hkdf_traffic,
.cipher = tlskey_hkdf_cipher,
.tbshash = tlskey_hkdf_tbshash,
}
static int tlskey_hkdf_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1093
static int tlskey_hkdf_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac __unused, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:1192
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1040
static int tlskey_hkdf_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:1123
static int tlskey_hkdf_save(struct tls_key_schedule *tlskey, const void *nonce, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1276
static int tlskey_hkdf_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1314
static int tlskey_hkdf_bind(const struct tls_preshared_key *psk, const void *hash, void *binder, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.c:1341
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:941
static int tlskey_hkdf_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1064
static int tlskey_hkdf_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data __unused, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:1235
static int tlskey_hkdf_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:1159

TLS key schedule based on HKDF.

Definition at line 1379 of file tlskey.c.

1379 {
1380 .name = "HKDF",
1381 .accumulates = 1,
1382 .mask = TLSKEY_KDF_KEYED,
1383 .secretsize = tlskey_hkdf_secretsize,
1384 .expand = tlskey_hkdf_expand,
1385 .reset = tlskey_hkdf_reset,
1386 .apply = tlskey_hkdf_apply,
1387 .master = tlskey_hkdf_master,
1388 .verify = tlskey_hkdf_verify,
1389 .traffic = tlskey_hkdf_traffic,
1390 .cipher = tlskey_hkdf_cipher,
1391 .tbshash = tlskey_hkdf_tbshash,
1392 .save = tlskey_hkdf_save,
1393 .load = tlskey_hkdf_load,
1394 .bind = tlskey_hkdf_bind,
1395};

Referenced by rfc8448_resumed_test(), rfc8448_simple_test(), and tls_set_digest().

◆ tlskey_hash

const struct tls_key_schedule_operations tlskey_hash
Initial value:
= {
.name = "P_Hash()",
.accumulates = 0,
.secretsize = tlskey_hash_secretsize,
.expand = tlskey_hash_expand,
.master = tlskey_hash_master,
.verify = tlskey_hash_verify,
.traffic = tlskey_hash_traffic,
.cipher = tlskey_hash_cipher,
.tbshash = tlskey_hash_tbshash,
}
static int tlskey_hash_tbshash(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, struct digest_algorithm *digest, const void *data, size_t len, void *tbs)
Generate signable digest value.
Definition tlskey.c:1697
static int tlskey_hash_cipher(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, void *key, size_t key_len, void *iv, size_t iv_len, void *mac, size_t mac_len)
Generate cipher key material.
Definition tlskey.c:1644
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1801
static int tlskey_hash_verify(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.c:1576
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1523
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1482
static int tlskey_hash_traffic(struct tls_key_schedule *tlskey, const struct tls_endpoint *writer, const struct tls_phase *phase)
Generate traffic secret.
Definition tlskey.c:1613
static int tlskey_hash_save(struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1768
static int tlskey_hash_bind(const struct tls_preshared_key *psk __unused, const void *hash __unused, void *binder __unused, size_t binder_len)
Generate pre-shared key binder value.
Definition tlskey.c:1828
static int tlskey_hash_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1499
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1413

TLS key schedule based on P_Hash().

Definition at line 1840 of file tlskey.c.

1840 {
1841 .name = "P_Hash()",
1842 .accumulates = 0,
1844 .secretsize = tlskey_hash_secretsize,
1845 .expand = tlskey_hash_expand,
1846 .reset = tlskey_hash_reset,
1847 .apply = tlskey_hash_apply,
1848 .master = tlskey_hash_master,
1849 .verify = tlskey_hash_verify,
1850 .traffic = tlskey_hash_traffic,
1851 .cipher = tlskey_hash_cipher,
1852 .tbshash = tlskey_hash_tbshash,
1853 .save = tlskey_hash_save,
1854 .load = tlskey_hash_load,
1855 .bind = tlskey_hash_bind,
1856};

Referenced by dummy_hash(), and tls_set_digest().

◆ tlskey_md5_sha1

const struct tls_key_schedule_operations tlskey_md5_sha1
Initial value:
= {
.name = "P_MD5()+P_SHA1()",
.accumulates = 0,
.master = tlskey_hash_master,
.verify = tlskey_hash_verify,
.traffic = tlskey_hash_traffic,
.cipher = tlskey_hash_cipher,
.tbshash = tlskey_hash_tbshash,
}
static void tlskey_md5_sha1_expand(struct digest_algorithm *digest, const void *secret, const char *label, const void *seed, size_t seed_len, void *out, size_t out_len)
Expand key material.
Definition tlskey.c:1898
static int tlskey_md5_sha1_save(struct tls_key_schedule *tlskey, const void *nonce __unused, size_t nonce_len, struct tls_preshared_key *psk)
Save pre-shared key.
Definition tlskey.c:1982
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1871
static int tlskey_md5_sha1_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:1937

TLS key schedule based on P_MD5()+P_SHA1().

Definition at line 2014 of file tlskey.c.

2014 {
2015 .name = "P_MD5()+P_SHA1()",
2016 .accumulates = 0,
2018 .secretsize = tlskey_md5_sha1_secretsize,
2019 .expand = tlskey_md5_sha1_expand,
2020 .reset = tlskey_hash_reset,
2021 .apply = tlskey_md5_sha1_apply,
2022 .master = tlskey_hash_master,
2023 .verify = tlskey_hash_verify,
2024 .traffic = tlskey_hash_traffic,
2025 .cipher = tlskey_hash_cipher,
2026 .tbshash = tlskey_hash_tbshash,
2027 .save = tlskey_md5_sha1_save,
2028 .load = tlskey_hash_load,
2029 .bind = tlskey_hash_bind,
2030};

Referenced by dummy_md5_sha1(), and tls_set_digest().