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 1395 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(), 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_change_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 /* Generate digest value */
763 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
764 tlskey, end->name, digest->name );
765 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
766 tbs ) ) != 0 ) {
767 return rc;
768 }
769 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
770 tlskey, end->name, digest->name );
771 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
772
773 return 0;
774}

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

Referenced by dummy_hash(), rfc8448_simple_test(), tls_new_server_key_exchange(), 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 785 of file tlskey.c.

786 {
787 const struct tls_key_schedule_operations *op = tlskey->op;
788 struct digest_algorithm *digest = tlskey->digest;
789 int rc;
790
791 /* Clear any existing pre-shared key */
792 memset ( psk, 0, sizeof ( *psk ) );
793
794 /* Sanity check */
795 if ( ! op )
796 return -ENOTTY;
797
798 /* Session resumption requires a master secret */
799 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
800 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
801 "secret\n", tlskey );
802 return -EPROTO;
803 }
804
805 /* Save key material */
806 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
807 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
808 return rc;
809 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
810 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
811
812 /* Record key properties */
813 psk->op = op;
814 psk->digest = digest;
815 psk->flags = tlskey->kdf.flags;
816
817 return 0;
818}
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 828 of file tlskey.c.

829 {
830 const struct tls_key_schedule_operations *op = tlskey->op;
831 struct digest_algorithm *digest = tlskey->digest;
832 int rc;
833
834 /* Reset key schedule */
835 tlskey_reset ( tlskey );
836
837 /* Sanity check */
838 if ( ! op )
839 return -ENOTTY;
840
841 /* Session resumption requires a master secret */
842 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
843 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
844 "secret\n", tlskey );
845 return -EPROTO;
846 }
847
848 /* Pre-shared key must match extended/non-extended usage */
849 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
850 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
851 "secret\n", tlskey, ( ems ? "non-" : "" ) );
852 return -EPERM;
853 }
854
855 /* Pre-shared key must match schedule and digest */
856 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
857 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
858 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
859 ( psk->digest ? psk->digest->name : "(unknown)" ) );
860 return -EPERM;
861 }
862
863 /* Load key material */
864 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
865 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
866 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
867 return rc;
868
869 /* Set flags */
870 tlskey->kdf.flags = ( psk->flags & op->mask );
871
872 return 0;
873}
#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 885 of file tlskey.c.

886 {
887 const struct tls_key_schedule_operations *op = psk->op;
888 struct digest_algorithm *digest = psk->digest;
889 int rc;
890
891 /* Generate prefix digest and binder value */
892 if ( op && digest ) {
893 size_t digestsize = digest->digestsize;
894 size_t ctxsize = digest->ctxsize;
897
898 /* Calculate prefix digest */
899 digest_init ( digest, ctx );
900 digest_update ( digest, ctx, prefix, prefix_len );
901 digest_final ( digest, ctx, out );
902
903 /* Generate binder value */
904 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
905 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
906 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
907 return rc;
908 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
909 DBGC_HDA ( psk, 0, binder, binder_len );
910
911 return 0;
912 }
913
914 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
915 return -ENOENT;
916}
#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 931 of file tlskey.c.

931 {
932 size_t digestsize = digest->digestsize;
933
934 return ( digestsize * 3 /* KDF, client, and server secrets */ );
935}

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 948 of file tlskey.c.

951 {
952 static const char prefix[6] = "tls13 ";
953 const void *context = seed;
954 size_t context_len = seed_len;
955 size_t prefix_len = sizeof ( prefix );
956 size_t label_len = strlen ( label );
957 struct {
959 uint8_t label_len;
960 char prefix[prefix_len];
961 char label[label_len];
962 uint8_t context_len;
963 uint8_t context[context_len];
964 } __attribute__ (( packed )) info;
965
966 /* Construct additional information */
967 info.len = htons ( out_len );
968 info.label_len = ( prefix_len + label_len );
969 memcpy ( info.prefix, prefix, prefix_len );
970 memcpy ( info.label, label, label_len );
971 info.context_len = context_len;
972 memcpy ( info.context, context, context_len );
973
974 /* Generate output using HKDF */
975 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
976}
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 984 of file tlskey.c.

985 {
986 size_t ctxsize = digest->ctxsize;
987 uint8_t ctx[ctxsize];
988
989 /* Calculate empty digest */
990 digest_init ( digest, ctx );
991 digest_final ( digest, ctx, empty );
992}

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 1002 of file tlskey.c.

1004 {
1005 size_t digestsize = digest->digestsize;
1006 size_t hctxsize = hmac_ctxsize ( digest );
1007 struct {
1008 uint8_t hctx[hctxsize];
1010 } tmp;
1011
1012 /* Generate HMAC key */
1013 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1014 tmp.key, sizeof ( tmp.key ) );
1015
1016 /* Generate HMAC */
1017 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1018 hmac_update ( digest, tmp.hctx, hash, digestsize );
1019 hmac_final ( digest, tmp.hctx, out );
1020
1021 /* Clear temporary secrets */
1022 memset ( &tmp, 0, sizeof ( tmp ) );
1023}
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:948

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 1030 of file tlskey.c.

1030 {
1031 struct digest_algorithm *digest = tlskey->digest;
1032 size_t digestsize = digest->digestsize;
1033 void *secret = tlskey->secret;
1034
1035 /* Allocate and initialise secrets */
1036 tlskey->kdf.secret = secret; secret += digestsize;
1037 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1038 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1039 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1040
1041 /* Initialise empty early secret */
1042 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1043 tlskey->kdf.secret );
1044}
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 1054 of file tlskey.c.

1055 {
1056 struct digest_algorithm *digest = tlskey->digest;
1057 size_t digestsize = digest->digestsize;
1058 uint8_t empty[digestsize];
1059
1060 /* Generate derived secret */
1061 tlskey_hkdf_empty ( digest, empty );
1062 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1063 digestsize, tlskey->kdf.secret, digestsize );
1064 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1065 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1066
1067 /* Extract new pseudorandom key */
1068 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1069 shared_len, tlskey->kdf.secret );
1070 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1071 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1072
1073 return 0;
1074}
static void tlskey_hkdf_empty(struct digest_algorithm *digest, void *empty)
Calculate empty digest value.
Definition tlskey.c:984
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 1083 of file tlskey.c.

1083 {
1084 struct digest_algorithm *digest = tlskey->digest;
1085 size_t digestsize = digest->digestsize;
1086 uint8_t zero[digestsize];
1087 int rc;
1088
1089 /* Extended master secret must always be used */
1090 if ( ! ems ) {
1091 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1092 "secret\n", tlskey );
1093 return -EPROTO;
1094 }
1095
1096 /* Generate master secret */
1097 memset ( zero, 0, sizeof ( zero ) );
1098 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1099 return rc;
1100
1101 return 0;
1102}
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 1113 of file tlskey.c.

1115 {
1116 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1117 struct digest_algorithm *digest = tlskey->digest;
1118 size_t digestsize = digest->digestsize;
1119
1120 /* Verification data must be a complete digest output */
1121 if ( verify_len != digestsize )
1122 return -EINVAL;
1123
1124 /* Verification data is derived from handshake secrets */
1125 if ( traffic->phase != &tls_handshake ) {
1126 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1127 "data without %s handshake traffic secrets\n",
1128 tlskey, end->name, end->name );
1129 return -EPROTO;
1130 }
1131
1132 /* Generate verification data */
1133 tlskey_hkdf_finished ( digest, traffic->secret,
1134 tlskey->transcript.running, verify );
1135 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1136 DBGC_HDA ( tlskey, 0, verify, verify_len );
1137
1138 return 0;
1139}
#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:1002

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 1149 of file tlskey.c.

1151 {
1152 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1153 struct digest_algorithm *digest = tlskey->digest;
1154 size_t digestsize = digest->digestsize;
1155 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1156
1157 /* Generate label */
1158 snprintf ( label, sizeof ( label ), "%c %s traffic",
1159 writer->name[0], phase->label );
1160
1161 /* Generate traffic secret */
1162 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1164 traffic->secret, digestsize );
1165
1166 return 0;
1167}
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 1182 of file tlskey.c.

1186 {
1187 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1188 struct digest_algorithm *digest = tlskey->digest;
1189 size_t digestsize = digest->digestsize;
1190 void *secret = traffic->secret;
1191
1192 /* The key schedule does not define a way to generate MAC secrets */
1193 if ( mac_len ) {
1194 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1195 tlskey );
1196 return -ENOTSUP;
1197 }
1198
1199 /* Generate cipher key */
1200 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1201
1202 /* Generate initialisation vector */
1203 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1204
1205 /* Update traffic secret, if applicable */
1206 if ( traffic->phase == &tls_application ) {
1207 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1208 secret, digestsize );
1209 }
1210
1211 return 0;
1212}
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 1225 of file tlskey.c.

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

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 1266 of file tlskey.c.

1268 {
1269 struct digest_algorithm *digest = tlskey->digest;
1270 size_t digestsize = digest->digestsize;
1271 struct {
1272 uint8_t master[digestsize];
1273 } tmp;
1274
1275 /* The pre-shared key currently uses a fixed-size buffer */
1276 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1277 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1278 tlskey, digest->name );
1279 return -ENOTSUP;
1280 }
1281
1282 /* Generate resumption master secret */
1283 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1285 tmp.master, sizeof ( tmp.master ) );
1286
1287 /* Generate resumption secret */
1288 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1289 psk->key.resumption, digestsize );
1290
1291 /* Clear temporary secrets */
1292 memset ( &tmp, 0, sizeof ( tmp ) );
1293
1294 return 0;
1295}
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 1304 of file tlskey.c.

1305 {
1306 struct digest_algorithm *digest = tlskey->digest;
1307 size_t digestsize = digest->digestsize;
1308
1309 /* Sanity checks */
1310 assert ( digest == psk->digest );
1311 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1312
1313 /* Extract early secret */
1314 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1315 tlskey->kdf.secret );
1316 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1317 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1318
1319 return 0;
1320}

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 1331 of file tlskey.c.

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

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 1403 of file tlskey.c.

1403 {
1404
1405 /* A P_Hash() key is an HMAC key */
1406 return hmac_keysize ( digest );
1407}
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 1420 of file tlskey.c.

1423 {
1424 size_t digestsize = digest->digestsize;
1425 size_t hctxsize = hmac_ctxsize ( digest );
1426 size_t frag_len = digestsize;
1427 size_t label_len = strlen ( label );
1428 unsigned int index = 0;
1429 struct {
1430 uint8_t ctx[2][hctxsize];
1432 uint8_t frag[digestsize];
1433 } tmp;
1434
1435 /* Generate as much output as required */
1436 while ( out_len ) {
1437
1438 /* Generate A(n) and output fragment */
1439 hmac_init_key ( digest, tmp.ctx[0], secret );
1440 if ( index ) {
1441 hmac_update ( digest, tmp.ctx[0], tmp.a,
1442 sizeof ( tmp.a ) );
1443 memcpy ( tmp.ctx[1], tmp.ctx[0],
1444 sizeof ( tmp.ctx[1] ) );
1445 }
1446 hmac_update ( digest, tmp.ctx[0], label, label_len );
1447 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1448 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1449 if ( index++ == 0 )
1450 continue;
1451 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1452
1453 /* Copy output */
1454 if ( frag_len > out_len )
1455 frag_len = out_len;
1456 memcpy ( out, tmp.frag, frag_len );
1457
1458 /* Move to next fragment */
1459 out += frag_len;
1460 out_len -= frag_len;
1461 }
1462
1463 /* Clear temporary secrets */
1464 memset ( &tmp, 0, sizeof ( tmp ) );
1465}
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 1472 of file tlskey.c.

1472 {
1473 void *secret = tlskey->secret;
1474
1475 /* Allocate and initialise secrets */
1476 tlskey->kdf.secret = secret;
1477 tlskey->traffic[TLS_CLIENT].secret = secret;
1478 tlskey->traffic[TLS_SERVER].secret = secret;
1479}

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 1489 of file tlskey.c.

1490 {
1491 struct digest_algorithm *digest = tlskey->digest;
1492 size_t hctxsize = hmac_ctxsize ( digest );
1493 struct {
1494 uint8_t hctx[hctxsize];
1495 } tmp;
1496
1497 /* Set HMAC key */
1498 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1499
1500 /* Clear temporary secrets */
1501 memset ( &tmp, 0, sizeof ( tmp ) );
1502
1503 return 0;
1504}
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 1513 of file tlskey.c.

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

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 1566 of file tlskey.c.

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

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 1603 of file tlskey.c.

1605 {
1606 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1607
1608 /* Only application phase keys are supported */
1609 if ( phase != &tls_application ) {
1610 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1611 tlskey, phase->name );
1612 return -ENOTSUP;
1613 }
1614
1615 /* There are no separate traffic secrets */
1616 assert ( traffic->secret == tlskey->kdf.secret );
1617
1618 return 0;
1619}

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 1634 of file tlskey.c.

1637 {
1638 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1639 struct {
1640 uint8_t key[total];
1641 } tmp;
1642 struct {
1643 struct tls_random server;
1644 struct tls_random client;
1645 } __attribute__ (( packed )) seed;
1646 const void *src;
1647 size_t mask;
1648
1649 /* Construct seed (with swapped client/server random bytes) */
1650 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1651 sizeof ( seed.server ) );
1652 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1653 sizeof ( seed.client ) );
1654
1655 /* Generate key material */
1656 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1657 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1658
1659 /* Partition key material */
1660 src = tmp.key;
1661 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1662 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1663 src += ( 2 * mac_len );
1664 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1665 src += ( 2 * key_len );
1666 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1667 src += ( 2 * iv_len );
1668 assert ( src == &tmp.key[total] );
1669
1670 /* Clear temporary secrets */
1671 memset ( &tmp, 0, sizeof ( tmp ) );
1672
1673 return 0;
1674}
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 1687 of file tlskey.c.

1690 {
1691 size_t ctxsize = digest->ctxsize;
1692 struct {
1693 uint8_t ctx[ctxsize];
1694 } tmp;
1695
1696 /* Generate endpoint-specific digest value */
1697 if ( end->index == TLS_CLIENT ) {
1698
1699 /* The client CertificateVerify digest value is the
1700 * raw transcript digest. We retain only a single
1701 * running transcript digest, and can therefore
1702 * provide this only for a digest algorithm that
1703 * matches our transcript digest algorithm.
1704 */
1705 if ( digest != tlskey->digest ) {
1706 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1707 "transcript digest\n", tlskey, digest->name );
1708 return -ENOTSUP;
1709 }
1710
1711 /* There is no way to incorporate additional data */
1712 if ( len ) {
1713 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1714 "with additional data\n", tlskey );
1715 return -ENOTSUP;
1716 }
1717
1718 /* Copy transcript digest value */
1719 memcpy ( tbs, tlskey->transcript.running,
1720 digest->digestsize );
1721
1722 } else {
1723
1724 /* Generate ServerKeyExchange digest */
1725 digest_init ( digest, tmp.ctx );
1726 digest_update ( digest, tmp.ctx, &tlskey->random,
1727 sizeof ( tlskey->random ) );
1728 digest_update ( digest, tmp.ctx, data, len );
1729 digest_final ( digest, tmp.ctx, tbs );
1730 }
1731
1732 /* Clear temporary secrets */
1733 memset ( &tmp, 0, sizeof ( tmp ) );
1734
1735 return 0;
1736}

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 1747 of file tlskey.c.

1749 {
1750 struct digest_algorithm *digest = tlskey->digest;
1751
1752 /* A ticket nonce is not supported */
1753 if ( nonce_len )
1754 return -ENOTSUP;
1755
1756 /* For TLS version 1.2, the pre-master secret may be any
1757 * length but the master secret is fixed at 48 bytes. This is
1758 * smaller than the block size for all supported digest
1759 * algorithms. The HMAC key constructed from the master
1760 * secret will therefore be just the zero-padded master secret
1761 * value. We can therefore preserve just these first 48 bytes
1762 * of the KDF master secret (ignoring the zero padding up to
1763 * the digest block size).
1764 */
1765 assert ( sizeof ( psk->key.master_secret ) <=
1766 hmac_keysize ( digest ) );
1767 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1768 sizeof ( psk->key.master_secret ) );
1769
1770 return 0;
1771}
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 1780 of file tlskey.c.

1781 {
1782 const void *secret;
1783 size_t secret_len;
1784 int rc;
1785
1786 /* For TLS versions 1.2 and earlier, the pre-shared key
1787 * material contains the master secret and so we just apply
1788 * this as the key derivation function secret.
1789 */
1790 secret = &psk->key.master_secret;
1791 secret_len = sizeof ( psk->key.master_secret );
1792 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1793 return rc;
1794
1795 return 0;
1796}

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 1807 of file tlskey.c.

1809 {
1810
1811 /* Binder values are not supported */
1812 if ( binder_len )
1813 return -ENOTSUP;
1814
1815 return 0;
1816}

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 1850 of file tlskey.c.

1850 {
1851 struct md5_sha1_hmac_keys *hkeys;
1852 size_t secretsize;
1853
1854 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1855 if ( digest != &md5_sha1_algorithm )
1856 return 0;
1857
1858 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1859 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1860 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1861 secretsize = sizeof ( *hkeys );
1862
1863 return secretsize;
1864}
struct digest_algorithm md5_algorithm
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:84
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 1877 of file tlskey.c.

1880 {
1881 const struct md5_sha1_hmac_keys *hkeys = secret;
1882 struct {
1883 uint8_t sha1[out_len];
1884 } tmp;
1885 uint8_t *xor;
1886 unsigned int i;
1887
1888 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1889 assert ( digest == &md5_sha1_algorithm );
1890
1891 /* Generate MD5 portion into output buffer */
1892 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1893 seed_len, out, out_len );
1894
1895 /* Generate SHA-1 portion into temporary buffer */
1896 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1897 seed_len, tmp.sha1, out_len );
1898
1899 /* XOR together into output buffer */
1900 xor = out;
1901 for ( i = 0 ; i < out_len ; i++ )
1902 xor[i] ^= tmp.sha1[i];
1903
1904 /* Clear temporary secrets */
1905 memset ( &tmp, 0, sizeof ( tmp ) );
1906}
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:1420

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 1916 of file tlskey.c.

1917 {
1918 struct digest_algorithm *digest = tlskey->digest;
1919 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1920 size_t hctxsize = hmac_ctxsize ( digest );
1921 struct {
1922 uint8_t hctx[hctxsize];
1923 } tmp;
1924 const void *shared_md5;
1925 const void *shared_sha1;
1926 size_t shared_sublen;
1927
1928 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1929 assert ( digest == &md5_sha1_algorithm );
1930
1931 /* Split secret into two, with an overlap of up to one byte */
1932 shared_sublen = ( ( shared_len + 1 ) / 2 );
1933 shared_md5 = shared;
1934 shared_sha1 = ( shared + shared_len - shared_sublen );
1935
1936 /* Set HMAC-MD5 key */
1937 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1938 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1939 hkeys->md5 );
1940
1941 /* Set HMAC-SHA1 key */
1942 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1943 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1944 hkeys->sha1 );
1945
1946 /* Clear temporary secrets */
1947 memset ( &tmp, 0, sizeof ( tmp ) );
1948
1949 return 0;
1950}

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 1961 of file tlskey.c.

1964 {
1965 struct digest_algorithm *digest = tlskey->digest;
1966 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1967
1968 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1969 assert ( digest == &md5_sha1_algorithm );
1970
1971 /* A ticket nonce is not supported */
1972 if ( nonce_len )
1973 return -ENOTSUP;
1974
1975 /* For TLS versions 1.1 and earlier, the pre-master secret may
1976 * be any length but the master secret is fixed at 48 bytes.
1977 * It will have been split to become 24 bytes in each of the
1978 * MD5 and SHA-1 HMAC keys.
1979 */
1980 assert ( sizeof ( psk->key.master_secret.md5 ) <=
1982 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
1984 memcpy ( psk->key.master_secret.md5, hkeys->md5,
1985 sizeof ( psk->key.master_secret.md5 ) );
1986 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
1987 sizeof ( psk->key.master_secret.sha1 ) );
1988
1989 return 0;
1990}
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:421
TLS server state.
Definition tls.h:431

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(), 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_change_cipher(), 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:1083
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:1182
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1030
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:1113
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:1266
static int tlskey_hkdf_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1304
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:1331
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:931
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:1054
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:1225
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:1149

TLS key schedule based on HKDF.

Definition at line 1369 of file tlskey.c.

1369 {
1370 .name = "HKDF",
1371 .accumulates = 1,
1372 .mask = TLSKEY_KDF_KEYED,
1373 .secretsize = tlskey_hkdf_secretsize,
1374 .expand = tlskey_hkdf_expand,
1375 .reset = tlskey_hkdf_reset,
1376 .apply = tlskey_hkdf_apply,
1377 .master = tlskey_hkdf_master,
1378 .verify = tlskey_hkdf_verify,
1379 .traffic = tlskey_hkdf_traffic,
1380 .cipher = tlskey_hkdf_cipher,
1381 .tbshash = tlskey_hkdf_tbshash,
1382 .save = tlskey_hkdf_save,
1383 .load = tlskey_hkdf_load,
1384 .bind = tlskey_hkdf_bind,
1385};

Referenced by rfc8448_resumed_test(), and rfc8448_simple_test().

◆ 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:1687
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:1634
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1780
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:1566
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1513
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1472
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:1603
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:1747
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:1807
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:1489
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1403

TLS key schedule based on P_Hash().

Definition at line 1819 of file tlskey.c.

1819 {
1820 .name = "P_Hash()",
1821 .accumulates = 0,
1823 .secretsize = tlskey_hash_secretsize,
1824 .expand = tlskey_hash_expand,
1825 .reset = tlskey_hash_reset,
1826 .apply = tlskey_hash_apply,
1827 .master = tlskey_hash_master,
1828 .verify = tlskey_hash_verify,
1829 .traffic = tlskey_hash_traffic,
1830 .cipher = tlskey_hash_cipher,
1831 .tbshash = tlskey_hash_tbshash,
1832 .save = tlskey_hash_save,
1833 .load = tlskey_hash_load,
1834 .bind = tlskey_hash_bind,
1835};

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:1877
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:1961
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1850
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:1916

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

Definition at line 1993 of file tlskey.c.

1993 {
1994 .name = "P_MD5()+P_SHA1()",
1995 .accumulates = 0,
1997 .secretsize = tlskey_md5_sha1_secretsize,
1998 .expand = tlskey_md5_sha1_expand,
1999 .reset = tlskey_hash_reset,
2000 .apply = tlskey_md5_sha1_apply,
2001 .master = tlskey_hash_master,
2002 .verify = tlskey_hash_verify,
2003 .traffic = tlskey_hash_traffic,
2004 .cipher = tlskey_hash_cipher,
2005 .tbshash = tlskey_hash_tbshash,
2006 .save = tlskey_md5_sha1_save,
2007 .load = tlskey_hash_load,
2008 .bind = tlskey_hash_bind,
2009};

Referenced by dummy_md5_sha1(), and tls_set_digest().