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.
void tlskey_message (struct tls_key_schedule *tlskey)
 Replace running transcript digest with a message hash of itself.
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_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_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 1433 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:185
const struct tls_key_schedule_operations * op
Key schedule operations.
Definition tlskey.h:115
void * secret
Secret(s).
Definition tlskey.h:124
size_t secretsize
Secret size.
Definition tlskey.h:119
struct tls_transcript transcript
Running handshake transcript digest.
Definition tlskey.h:129
struct tls_random nonce
Local endpoint random bytes.
Definition tlskey.h:131
struct digest_algorithm * digest
Digest algorithm.
Definition tlskey.h:117
void * dynamic
Dynamically-allocated storage.
Definition tlskey.h:122
void * finishing
Running digest value up to the most recent Finished (if any).
Definition tlskey.h:76
void * running
Running digest value.
Definition tlskey.h:65
void * ctx
Digest context.
Definition tlskey.h:57
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:520
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_hrr_test(), 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:133
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:82

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:55
#define TLSKEY_TSF_FINISHED
Transcript digest includes a Finished record.
Definition tlskey.h:85

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 /* Do nothing if key schedule is stopped */
428 if ( ! digestsize )
429 return;
430
431 /* Append to running transcript digest */
432 digest_update ( digest, transcript->ctx, data, len );
433
434 /* Update running transcript digest output */
435 memcpy ( tmp.ctx, transcript->ctx, ctxsize );
436 digest_final ( digest, tmp.ctx, transcript->running );
437
438 /* Process digested handshake record */
439 flags = tlskey_handshake ( tlskey, data, len );
440 transcript->flags |= flags;
441
442 /* Update the finishing digest value, if applicable */
443 if ( ! ( ( transcript->flags ^ flags ) & TLSKEY_TSF_FINISHED ) ) {
444 memcpy ( transcript->finishing, transcript->running,
445 digestsize );
446 }
447
448 /* Clear temporary secrets */
449 memset ( &tmp, 0, sizeof ( tmp ) );
450}
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:78
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_hrr_test(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_add_handshake(), tlskey_message(), and tlskey_start().

◆ tlskey_message()

void tlskey_message ( struct tls_key_schedule * tlskey)

Replace running transcript digest with a message hash of itself.

Parameters
tlskeyKey schedule

Definition at line 457 of file tlskey.c.

457 {
458 struct tls_transcript *transcript = &tlskey->transcript;
459 struct digest_algorithm *digest = tlskey->digest;
460 size_t digestsize = digest->digestsize;
461 struct tls_message_hash msg;
462
463 /* Construct message hash header */
464 msg.type = TLS_MESSAGE_HASH;
465 msg.zero = 0;
466 msg.len = digestsize;
467
468 /* Replace running transcript digest */
469 digest_init ( digest, transcript->ctx );
470 digest_update ( digest, transcript->ctx, &msg, sizeof ( msg ) );
471 digest_update ( digest, transcript->ctx, transcript->running,
472 digestsize );
473 tlskey_digest ( tlskey, NULL, 0 );
474}
void msg(unsigned int row, const char *fmt,...)
Print message centred on specified row.
Definition message.c:62
A message hash prefix.
Definition tlskey.h:42
#define TLS_MESSAGE_HASH
A TLS message hash.
Definition tlskey.h:52

References tls_transcript::ctx, tls_key_schedule::digest, digest_init(), digest_update(), digest_algorithm::digestsize, digestsize, msg(), NULL, tls_transcript::running, TLS_MESSAGE_HASH, tlskey_digest(), and tls_key_schedule::transcript.

Referenced by rfc8448_hrr_test(), and tls_new_server_hello().

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

497 {
498 const struct tls_key_schedule_operations *op = tlskey->op;
499 struct digest_algorithm *digest = tlskey->digest;
500
501 /* Sanity check */
502 assert ( op != NULL );
503
504 /* Expand key material */
505 DBGC2 ( tlskey, "TLSKEY %p expanding seed \"%s\":\n", tlskey, label );
506 DBGC2_HDA ( tlskey, 0, seed, seed_len );
507 op->expand ( digest, secret, label, seed, seed_len, out, out_len );
508 DBGC2 ( tlskey, "TLSKEY %p expanded:\n", tlskey );
509 DBGC2_HDA ( tlskey, 0, out, out_len );
510}
__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:183

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

520 {
521 const struct tls_key_schedule_operations *op = tlskey->op;
522
523 /* Do nothing if key schedule is stopped */
524 if ( ! op ) {
525 assert ( tlskey->secretsize == 0 );
526 assert ( tlskey->kdf.flags == 0 );
527 assert ( tlskey->traffic[TLS_CLIENT].phase == NULL );
528 assert ( tlskey->traffic[TLS_SERVER].phase == NULL );
529 return;
530 }
531
532 /* Clear secrets, flags, and traffic phases */
533 memset ( tlskey->secret, 0, tlskey->secretsize );
534 tlskey->kdf.flags = 0;
535 tlskey->traffic[TLS_CLIENT].phase = NULL;
536 tlskey->traffic[TLS_SERVER].phase = NULL;
537
538 /* Reset key schedule */
539 op->reset ( tlskey );
540}
unsigned int flags
Key flags.
Definition tlskey.h:92
struct tls_traffic_secret traffic[2]
Traffic secrets.
Definition tlskey.h:137
struct tls_kdf_secret kdf
Key derivation function secret.
Definition tlskey.h:135
const struct tls_phase * phase
Phase.
Definition tlskey.h:109

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

551 {
552 const struct tls_key_schedule_operations *op = tlskey->op;
553 int rc;
554
555 /* Sanity check */
556 if ( ! op )
557 return -ENOTTY;
558
559 /* All schedules define the master secret as immutable */
560 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
561 DBGC ( tlskey, "TLSKEY %p cannot apply a new shared secret "
562 "after generating master secret\n", tlskey );
563 return -EPROTO;
564 }
565
566 /* Apply new shared secret */
567 DBGC ( tlskey, "TLSKEY %p applying secret:\n", tlskey );
568 DBGC_HDA ( tlskey, 0, shared, shared_len );
569 if ( ( rc = op->apply ( tlskey, shared, shared_len ) ) != 0 )
570 return rc;
571
572 /* Mark key schedule as containing key material */
573 tlskey->kdf.flags |= TLSKEY_KDF_KEYED;
574
575 return 0;
576}
#define EPROTO
Protocol error.
Definition errno.h:668
#define TLSKEY_KDF_MASTER
Key derivation function has a master secret.
Definition tlskey.h:99
#define TLSKEY_KDF_KEYED
Key derivation function has key material.
Definition tlskey.h:96

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_hrr_test(), 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 585 of file tlskey.c.

585 {
586 const struct tls_key_schedule_operations *op = tlskey->op;
587 int rc;
588
589 /* Sanity check */
590 if ( ! op )
591 return -ENOTTY;
592
593 /* Any conceivable schedule requires key material */
594 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
595 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
596 "without key material\n", tlskey );
597 return -EPROTO;
598 }
599
600 /* All schedules define the master secret as immutable */
601 if ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) {
602 DBGC ( tlskey, "TLSKEY %p cannot regenerate master secret\n",
603 tlskey );
604 return -EPROTO;
605 }
606
607 /* Generate master secret */
608 DBGC ( tlskey, "TLSKEY %p generating %smaster secret\n",
609 tlskey, ( ems ? "extended " : "" ) );
610 if ( ( rc = op->master ( tlskey, ems ) ) != 0 )
611 return rc;
612
613 /* Mark key schedule as containing master secret */
614 tlskey->kdf.flags |= TLSKEY_KDF_MASTER;
615 if ( ems )
616 tlskey->kdf.flags |= TLSKEY_KDF_EMS;
617
618 return 0;
619}
#define TLSKEY_KDF_EMS
Key derivation function has an extended master secret.
Definition tlskey.h:102

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

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

◆ tlskey_verify()

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

Generate verification data.

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

Definition at line 630 of file tlskey.c.

632 {
633 const struct tls_key_schedule_operations *op = tlskey->op;
634 int rc;
635
636 /* Sanity check */
637 if ( ! op )
638 return -ENOTTY;
639
640 /* Verification data must be non-replayable */
641 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
642 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
643 "without a digested nonce\n", tlskey );
644 return -EPROTO;
645 }
646
647 /* Generate verification data */
648 DBGC2 ( tlskey, "TLSKEY %p generating %s verification data\n",
649 tlskey, end->name );
650 if ( ( rc = op->verify ( tlskey, end, verify, verify_len ) ) != 0 )
651 return rc;
652 DBGC ( tlskey, "TLSKEY %p %s verification data:\n",
653 tlskey, end->name );
654 DBGC_HDA ( tlskey, 0, verify, verify_len );
655
656 return 0;
657}
int(* verify)(struct tls_key_schedule *tlskey, const struct tls_endpoint *end, void *verify, size_t verify_len)
Generate verification data.
Definition tlskey.h:256

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

669 {
670 const struct tls_key_schedule_operations *op = tlskey->op;
671 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
672 unsigned int missing;
673 int rc;
674
675 /* Sanity check */
676 if ( ! op )
677 return -ENOTTY;
678
679 /* Check flags required for this traffic phase */
681 missing = ( ( tlskey->kdf.flags ^ phase->flags ) & phase->flags );
682 if ( missing ) {
683 DBGC ( tlskey, "TLSKEY %p cannot generate %s %s traffic "
684 "secrets (missing KDF flags %#04x)\n",
685 tlskey, writer->name, phase->name, missing );
686 return -EPROTO;
687 }
688
689 /* Generate traffic secret */
690 DBGC2 ( tlskey, "TLSKEY %p generating %s %s traffic secret\n",
691 tlskey, writer->name, phase->name );
692 if ( ( rc = op->traffic ( tlskey, writer, phase ) ) != 0 )
693 return rc;
694
695 /* Record phase */
696 traffic->phase = phase;
697
698 return 0;
699}
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:105

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_hrr_test(), rfc8448_resumed_test(), rfc8448_simple_test(), and tls_prep_cipher().

◆ tlskey_cipher()

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

Generate cipher key material.

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

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

Definition at line 719 of file tlskey.c.

722 {
723 const struct tls_key_schedule_operations *op = tlskey->op;
724 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
725 int rc;
726
727 /* Sanity check */
728 if ( ! op )
729 return -ENOTTY;
730
731 /* Ensure that traffic secret has actually been generated */
732 if ( ! traffic->phase ) {
733 DBGC ( tlskey, "TLSKEY %p cannot generate cipher key "
734 "material without traffic secrets\n", tlskey );
735 return -EPROTO;
736 }
737
738 /* Generate cipher key material */
739 DBGC2 ( tlskey, "TLSKEY %p generating %s %s cipher key material\n",
740 tlskey, writer->name, traffic->phase->name );
741 if ( ( rc = op->cipher ( tlskey, writer, key, key_len, iv, iv_len,
742 mac, mac_len ) ) != 0 ) {
743 return rc;
744 }
745 if ( key_len ) {
746 DBGC ( tlskey, "TLSKEY %p %s key:\n", tlskey, writer->name );
747 DBGC_HDA ( tlskey, 0, key, key_len );
748 }
749 if ( iv_len ) {
750 DBGC ( tlskey, "TLSKEY %p %s IV:\n", tlskey, writer->name );
751 DBGC_HDA ( tlskey, 0, iv, iv_len );
752 }
753 if ( mac_len ) {
754 DBGC ( tlskey, "TLSKEY %p %s MAC:\n", tlskey, writer->name );
755 DBGC_HDA ( tlskey, 0, mac, mac_len );
756 }
757
758 return 0;
759}
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 772 of file tlskey.c.

775 {
776 const struct tls_key_schedule_operations *op = tlskey->op;
777 int rc;
778
779 /* Sanity check */
780 if ( ! op )
781 return -ENOTTY;
782
783 /* Signable digest values must be non-replayable */
784 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
785 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
786 "without a digested nonce\n", tlskey );
787 return -EPROTO;
788 }
789
790 /* Signable digest values must be constructed over the
791 * parameters used to establish a shared secret, and so a
792 * shared secret must exist.
793 */
794 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_KEYED ) ) {
795 DBGC ( tlskey, "TLSKEY %p cannot generate signable digest "
796 "without a shared secret\n", tlskey );
797 return -EPROTO;
798 }
799
800 /* Generate digest value */
801 DBGC2 ( tlskey, "TLSKEY %p generating signable %s %s digest\n",
802 tlskey, end->name, digest->name );
803 if ( ( rc = op->tbshash ( tlskey, end, digest, data, len,
804 tbs ) ) != 0 ) {
805 return rc;
806 }
807 DBGC ( tlskey, "TLSKEY %p generated signable %s %s digest:\n",
808 tlskey, end->name, digest->name );
809 DBGC_HDA ( tlskey, 0, tbs, digest->digestsize );
810
811 return 0;
812}

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

Referenced by dummy_hash(), rfc8448_simple_test(), tls_hash_sign(), and tls_hash_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 823 of file tlskey.c.

824 {
825 const struct tls_key_schedule_operations *op = tlskey->op;
826 struct digest_algorithm *digest = tlskey->digest;
827 int rc;
828
829 /* Clear any existing pre-shared key */
830 memset ( psk, 0, sizeof ( *psk ) );
831
832 /* Sanity check */
833 if ( ! op )
834 return -ENOTTY;
835
836 /* Session resumption requires a master secret */
837 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
838 DBGC ( tlskey, "TLSKEY %p cannot save key without a master "
839 "secret\n", tlskey );
840 return -EPROTO;
841 }
842
843 /* Save key material */
844 DBGC2 ( tlskey, "TLSKEY %p saving key\n", tlskey );
845 if ( ( rc = op->save ( tlskey, nonce, nonce_len, psk ) ) != 0 )
846 return rc;
847 DBGC ( tlskey, "TLSKEY %p saved key:\n", tlskey );
848 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
849
850 /* Record key properties */
851 psk->op = op;
852 psk->digest = digest;
853 psk->flags = tlskey->kdf.flags;
854
855 return 0;
856}
struct digest_algorithm * digest
Digest algorithm (if set).
Definition tlskey.h:145
unsigned int flags
Key flags.
Definition tlskey.h:147
union tls_preshared_key::@022173016027117201055347232316162256252261104170 key
Key material.
const struct tls_key_schedule_operations * op
Key schedule operations (if set).
Definition tlskey.h:143

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

867 {
868 const struct tls_key_schedule_operations *op = tlskey->op;
869 struct digest_algorithm *digest = tlskey->digest;
870 int rc;
871
872 /* Reset key schedule */
873 tlskey_reset ( tlskey );
874
875 /* Sanity check */
876 if ( ! op )
877 return -ENOTTY;
878
879 /* Session resumption requires a master secret */
880 if ( ! ( psk->flags & TLSKEY_KDF_MASTER ) ) {
881 DBGC ( tlskey, "TLSKEY %p cannot load from a non-master "
882 "secret\n", tlskey );
883 return -EPROTO;
884 }
885
886 /* Pre-shared key must match extended/non-extended usage */
887 if ( ( !! ems ) != ( !! ( psk->flags & TLSKEY_KDF_EMS ) ) ) {
888 DBGC ( tlskey, "TLSKEY %p cannot load from %sextended master "
889 "secret\n", tlskey, ( ems ? "non-" : "" ) );
890 return -EPERM;
891 }
892
893 /* Pre-shared key must match schedule and digest */
894 if ( ( op != psk->op ) || ( digest != psk->digest ) ) {
895 DBGC ( tlskey, "TLSKEY %p cannot load from %s with %s\n",
896 tlskey, ( psk->op ? psk->op->name : "(unknown)" ),
897 ( psk->digest ? psk->digest->name : "(unknown)" ) );
898 return -EPERM;
899 }
900
901 /* Load key material */
902 DBGC ( tlskey, "TLSKEY %p loading key:\n", tlskey );
903 DBGC_HDA ( tlskey, 0, &psk->key, sizeof ( psk->key ) );
904 if ( ( rc = op->load ( tlskey, psk ) ) != 0 )
905 return rc;
906
907 /* Set flags */
908 tlskey->kdf.flags = ( psk->flags & op->mask );
909
910 return 0;
911}
#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 923 of file tlskey.c.

924 {
925 const struct tls_key_schedule_operations *op = psk->op;
926 struct digest_algorithm *digest = psk->digest;
927 int rc;
928
929 /* Generate prefix digest and binder value */
930 if ( op && digest ) {
931 size_t digestsize = digest->digestsize;
932 size_t ctxsize = digest->ctxsize;
935
936 /* Calculate prefix digest */
937 digest_init ( digest, ctx );
938 digest_update ( digest, ctx, prefix, prefix_len );
939 digest_final ( digest, ctx, out );
940
941 /* Generate binder value */
942 DBGC2 ( psk, "TLSKEY %p generating key binder:\n", psk );
943 DBGC2_HDA ( psk, 0, &psk->key, sizeof ( psk->key ) );
944 if ( ( rc = op->bind ( psk, out, binder, binder_len ) ) != 0 )
945 return rc;
946 DBGC ( psk, "TLSKEY %p generated key binder:\n", psk );
947 DBGC_HDA ( psk, 0, binder, binder_len );
948
949 return 0;
950 }
951
952 DBGC ( psk, "TLSKEY %p cannot bind empty pre-shared key\n", psk );
953 return -ENOENT;
954}
#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 969 of file tlskey.c.

969 {
970 size_t digestsize = digest->digestsize;
971
972 return ( digestsize * 3 /* KDF, client, and server secrets */ );
973}

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

989 {
990 static const char prefix[6] = "tls13 ";
991 const void *context = seed;
992 size_t context_len = seed_len;
993 size_t prefix_len = sizeof ( prefix );
994 size_t label_len = strlen ( label );
995 struct {
997 uint8_t label_len;
998 char prefix[prefix_len];
999 char label[label_len];
1000 uint8_t context_len;
1001 uint8_t context[context_len];
1002 } __attribute__ (( packed )) info;
1003
1004 /* Construct additional information */
1005 info.len = htons ( out_len );
1006 info.label_len = ( prefix_len + label_len );
1007 memcpy ( info.prefix, prefix, prefix_len );
1008 memcpy ( info.label, label, label_len );
1009 info.context_len = context_len;
1010 memcpy ( info.context, context, context_len );
1011
1012 /* Generate output using HKDF */
1013 hkdf_expand ( digest, secret, &info, sizeof ( info ), out, out_len );
1014}
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 1022 of file tlskey.c.

1023 {
1024 size_t ctxsize = digest->ctxsize;
1025 uint8_t ctx[ctxsize];
1026
1027 /* Calculate empty digest */
1028 digest_init ( digest, ctx );
1029 digest_final ( digest, ctx, empty );
1030}

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

1042 {
1043 size_t digestsize = digest->digestsize;
1044 size_t hctxsize = hmac_ctxsize ( digest );
1045 struct {
1046 uint8_t hctx[hctxsize];
1048 } tmp;
1049
1050 /* Generate HMAC key */
1051 tlskey_hkdf_expand ( digest, secret, "finished", NULL, 0,
1052 tmp.key, sizeof ( tmp.key ) );
1053
1054 /* Generate HMAC */
1055 hmac_init ( digest, tmp.hctx, tmp.key, sizeof ( tmp.key ) );
1056 hmac_update ( digest, tmp.hctx, hash, digestsize );
1057 hmac_final ( digest, tmp.hctx, out );
1058
1059 /* Clear temporary secrets */
1060 memset ( &tmp, 0, sizeof ( tmp ) );
1061}
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:986

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

1068 {
1069 struct digest_algorithm *digest = tlskey->digest;
1070 size_t digestsize = digest->digestsize;
1071 void *secret = tlskey->secret;
1072
1073 /* Allocate and initialise secrets */
1074 tlskey->kdf.secret = secret; secret += digestsize;
1075 tlskey->traffic[TLS_CLIENT].secret = secret; secret += digestsize;
1076 tlskey->traffic[TLS_SERVER].secret = secret; secret += digestsize;
1077 assert ( secret == ( tlskey->secret + tlskey->secretsize ) );
1078
1079 /* Initialise empty early secret */
1080 hkdf_extract ( digest, NULL, 0, tlskey->kdf.secret, digestsize,
1081 tlskey->kdf.secret );
1082}
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:90
void * secret
Secret.
Definition tlskey.h:107

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

1093 {
1094 struct digest_algorithm *digest = tlskey->digest;
1095 size_t digestsize = digest->digestsize;
1096 uint8_t empty[digestsize];
1097
1098 /* Generate derived secret */
1099 tlskey_hkdf_empty ( digest, empty );
1100 tlskey_expand ( tlskey, tlskey->kdf.secret, "derived", empty,
1101 digestsize, tlskey->kdf.secret, digestsize );
1102 DBGC2 ( tlskey, "TLSKEY %p derived:\n", tlskey );
1103 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1104
1105 /* Extract new pseudorandom key */
1106 hkdf_extract ( digest, tlskey->kdf.secret, digestsize, shared,
1107 shared_len, tlskey->kdf.secret );
1108 DBGC2 ( tlskey, "TLSKEY %p extracted PRK:\n", tlskey );
1109 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1110
1111 return 0;
1112}
static void tlskey_hkdf_empty(struct digest_algorithm *digest, void *empty)
Calculate empty digest value.
Definition tlskey.c:1022
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:494

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

1121 {
1122 struct digest_algorithm *digest = tlskey->digest;
1123 size_t digestsize = digest->digestsize;
1124 uint8_t zero[digestsize];
1125 int rc;
1126
1127 /* Extended master secret must always be used */
1128 if ( ! ems ) {
1129 DBGC ( tlskey, "TLSKEY %p requires an extended master "
1130 "secret\n", tlskey );
1131 return -EPROTO;
1132 }
1133
1134 /* Generate master secret */
1135 memset ( zero, 0, sizeof ( zero ) );
1136 if ( ( rc = tlskey_apply ( tlskey, zero, sizeof ( zero ) ) ) != 0 )
1137 return rc;
1138
1139 return 0;
1140}
int tlskey_apply(struct tls_key_schedule *tlskey, const void *shared, size_t shared_len)
Apply a new shared secret.
Definition tlskey.c:550

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

1153 {
1154 struct tls_traffic_secret *traffic = &tlskey->traffic[end->index];
1155 struct digest_algorithm *digest = tlskey->digest;
1156 size_t digestsize = digest->digestsize;
1157
1158 /* Verification data must be a complete digest output */
1159 if ( verify_len != digestsize )
1160 return -EINVAL;
1161
1162 /* Verification data is derived from handshake secrets */
1163 if ( traffic->phase != &tls_handshake ) {
1164 DBGC ( tlskey, "TLSKEY %p cannot generate %s verification "
1165 "data without %s handshake traffic secrets\n",
1166 tlskey, end->name, end->name );
1167 return -EPROTO;
1168 }
1169
1170 /* Generate verification data */
1171 tlskey_hkdf_finished ( digest, traffic->secret,
1172 tlskey->transcript.running, verify );
1173 DBGC ( tlskey, "TLSKEY %p %s verification:\n", tlskey, end->name );
1174 DBGC_HDA ( tlskey, 0, verify, verify_len );
1175
1176 return 0;
1177}
#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:1040

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

1189 {
1190 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1191 struct digest_algorithm *digest = tlskey->digest;
1192 size_t digestsize = digest->digestsize;
1193 char label[ 13 /* "[c|s] [e|hs|ap] traffic" + NUL */ ];
1194
1195 /* Generate label */
1196 snprintf ( label, sizeof ( label ), "%c %s traffic",
1197 writer->name[0], phase->label );
1198
1199 /* Generate traffic secret */
1200 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1202 traffic->secret, digestsize );
1203
1204 return 0;
1205}
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 1220 of file tlskey.c.

1224 {
1225 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1226 struct digest_algorithm *digest = tlskey->digest;
1227 size_t digestsize = digest->digestsize;
1228 void *secret = traffic->secret;
1229
1230 /* The key schedule does not define a way to generate MAC secrets */
1231 if ( mac_len ) {
1232 DBGC ( tlskey, "TLSKEY %p does not support MAC secrets\n",
1233 tlskey );
1234 return -ENOTSUP;
1235 }
1236
1237 /* Generate cipher key */
1238 tlskey_expand ( tlskey, secret, "key", NULL, 0, key, key_len );
1239
1240 /* Generate initialisation vector */
1241 tlskey_expand ( tlskey, secret, "iv", NULL, 0, iv, iv_len );
1242
1243 /* Update traffic secret, if applicable */
1244 if ( traffic->phase == &tls_application ) {
1245 tlskey_expand ( tlskey, secret, "traffic upd", NULL, 0,
1246 secret, digestsize );
1247 }
1248
1249 return 0;
1250}
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 1263 of file tlskey.c.

1267 {
1268 size_t ctxsize = digest->ctxsize;
1269 uint8_t ctx[ctxsize];
1270 char buf[64];
1271 int label_len;
1272
1273 /* There is no way to incorporate additional data */
1274 if ( len ) {
1275 DBGC ( tlskey, "TLSKEY %p cannot generate digest with "
1276 "additional data\n", tlskey );
1277 return -ENOTSUP;
1278 }
1279
1280 /* Generate digest value (all input is public) */
1281 digest_init ( digest, ctx );
1282 memset ( buf, 0x20, sizeof ( buf ) );
1283 digest_update ( digest, ctx, buf, sizeof ( buf ) );
1284 label_len = snprintf ( buf, sizeof ( buf ),
1285 "TLS 1.3, %s CertificateVerify", end->name );
1286 assert ( label_len == 33 /* for both "client" and "server" */ );
1287 digest_update ( digest, ctx, buf, ( label_len + 1 /* NUL */ ) );
1288 digest_update ( digest, ctx, tlskey->transcript.running,
1289 tlskey->digest->digestsize );
1290 digest_final ( digest, ctx, tbs );
1291
1292 return 0;
1293}

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

1306 {
1307 struct digest_algorithm *digest = tlskey->digest;
1308 size_t digestsize = digest->digestsize;
1309 struct {
1310 uint8_t master[digestsize];
1311 } tmp;
1312
1313 /* The pre-shared key currently uses a fixed-size buffer */
1314 if ( digestsize > sizeof ( psk->key.resumption ) ) {
1315 DBGC ( tlskey, "TLSKEY %p cannot save %s pre-shared key\n",
1316 tlskey, digest->name );
1317 return -ENOTSUP;
1318 }
1319
1320 /* Generate resumption master secret */
1321 tlskey_expand ( tlskey, tlskey->kdf.secret, "res master",
1323 tmp.master, sizeof ( tmp.master ) );
1324
1325 /* Generate resumption secret */
1326 tlskey_expand ( tlskey, tmp.master, "resumption", nonce, nonce_len,
1327 psk->key.resumption, digestsize );
1328
1329 /* Clear temporary secrets */
1330 memset ( &tmp, 0, sizeof ( tmp ) );
1331
1332 return 0;
1333}
uint8_t resumption[48]
Resumption secret.
Definition tlskey.h:178

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

1343 {
1344 struct digest_algorithm *digest = tlskey->digest;
1345 size_t digestsize = digest->digestsize;
1346
1347 /* Sanity checks */
1348 assert ( digest == psk->digest );
1349 assert ( digestsize <= sizeof ( psk->key.resumption ) );
1350
1351 /* Extract early secret */
1352 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize,
1353 tlskey->kdf.secret );
1354 DBGC2 ( tlskey, "TLSKEY %p early secret:\n", tlskey );
1355 DBGC2_HDA ( tlskey, 0, tlskey->kdf.secret, digestsize );
1356
1357 return 0;
1358}

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

1371 {
1372 struct digest_algorithm *digest = psk->digest;
1373 size_t digestsize = digest->digestsize;
1374 uint8_t empty[digestsize];
1375 struct {
1377 } tmp;
1378
1379 /* Binder value must be a complete digest output */
1380 if ( binder_len != digestsize )
1381 return -EINVAL;
1382
1383 /* Extract temporary copy of early secret */
1384 hkdf_extract ( digest, NULL, 0, &psk->key, digestsize, tmp.key );
1385 DBGC2 ( psk, "TLSKEY %p temporary early secret:\n", psk );
1386 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1387
1388 /* Generate resumption binder secret */
1389 tlskey_hkdf_empty ( digest, empty );
1390 tlskey_hkdf_expand ( digest, tmp.key, "res binder", empty, digestsize,
1391 tmp.key, digestsize );
1392 DBGC2 ( psk, "TLSKEY %p resumption binder secret:\n", psk );
1393 DBGC2_HDA ( psk, 0, tmp.key, sizeof ( tmp.key ) );
1394
1395 /* Generate binder */
1396 tlskey_hkdf_finished ( digest, tmp.key, hash, binder );
1397 DBGC2 ( psk, "TLSKEY %p binder:\n", psk );
1398 DBGC2_HDA ( psk, 0, binder, binder_len );
1399
1400 /* Clear temporary secrets */
1401 memset ( &tmp, 0, sizeof ( tmp ) );
1402
1403 return 0;
1404}

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

1441 {
1442
1443 /* A P_Hash() key is an HMAC key */
1444 return hmac_keysize ( digest );
1445}
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 1458 of file tlskey.c.

1461 {
1462 size_t digestsize = digest->digestsize;
1463 size_t hctxsize = hmac_ctxsize ( digest );
1464 size_t frag_len = digestsize;
1465 size_t label_len = strlen ( label );
1466 unsigned int index = 0;
1467 struct {
1468 uint8_t ctx[2][hctxsize];
1470 uint8_t frag[digestsize];
1471 } tmp;
1472
1473 /* Generate as much output as required */
1474 while ( out_len ) {
1475
1476 /* Generate A(n) and output fragment */
1477 hmac_init_key ( digest, tmp.ctx[0], secret );
1478 if ( index ) {
1479 hmac_update ( digest, tmp.ctx[0], tmp.a,
1480 sizeof ( tmp.a ) );
1481 memcpy ( tmp.ctx[1], tmp.ctx[0],
1482 sizeof ( tmp.ctx[1] ) );
1483 }
1484 hmac_update ( digest, tmp.ctx[0], label, label_len );
1485 hmac_update ( digest, tmp.ctx[0], seed, seed_len );
1486 hmac_final ( digest, tmp.ctx[ ( index != 0 ) ], tmp.a );
1487 if ( index++ == 0 )
1488 continue;
1489 hmac_final ( digest, tmp.ctx[0], tmp.frag );
1490
1491 /* Copy output */
1492 if ( frag_len > out_len )
1493 frag_len = out_len;
1494 memcpy ( out, tmp.frag, frag_len );
1495
1496 /* Move to next fragment */
1497 out += frag_len;
1498 out_len -= frag_len;
1499 }
1500
1501 /* Clear temporary secrets */
1502 memset ( &tmp, 0, sizeof ( tmp ) );
1503}
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 1510 of file tlskey.c.

1510 {
1511 void *secret = tlskey->secret;
1512
1513 /* Allocate and initialise secrets */
1514 tlskey->kdf.secret = secret;
1515 tlskey->traffic[TLS_CLIENT].secret = secret;
1516 tlskey->traffic[TLS_SERVER].secret = secret;
1517}

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

1528 {
1529 struct digest_algorithm *digest = tlskey->digest;
1530 size_t hctxsize = hmac_ctxsize ( digest );
1531 struct {
1532 uint8_t hctx[hctxsize];
1533 } tmp;
1534
1535 /* Set HMAC key */
1536 hmac_key ( digest, tmp.hctx, shared, shared_len, tlskey->kdf.secret );
1537
1538 /* Clear temporary secrets */
1539 memset ( &tmp, 0, sizeof ( tmp ) );
1540
1541 return 0;
1542}
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 1551 of file tlskey.c.

1551 {
1552 struct digest_algorithm *digest = tlskey->digest;
1553 size_t digestsize = digest->digestsize;
1554 const char *label;
1555 const void *seed;
1556 size_t seed_len;
1557 struct {
1558 uint8_t master[48];
1559 } tmp;
1560 int rc;
1561
1562 /* Master secret is derived from the client and server random
1563 * values (or the full transcript digest).
1564 */
1565 if ( ! ( tlskey->transcript.flags & TLSKEY_TSF_NONCED ) ) {
1566 DBGC ( tlskey, "TLSKEY %p cannot generate master secret "
1567 "without a digested nonce\n", tlskey );
1568 return -EPROTO;
1569 }
1570
1571 /* Generate master secret */
1572 if ( ems ) {
1573 label = "extended master secret";
1574 seed = tlskey->transcript.running;
1575 seed_len = digestsize;
1576 } else {
1577 label = "master secret";
1578 seed = &tlskey->random;
1579 seed_len = sizeof ( tlskey->random );
1580 }
1581 tlskey_expand ( tlskey, tlskey->kdf.secret, label, seed, seed_len,
1582 tmp.master, sizeof ( tmp.master ) );
1583
1584 /* Apply master secret */
1585 if ( ( rc = tlskey_apply ( tlskey, tmp.master,
1586 sizeof ( tmp.master ) ) ) != 0 ) {
1587 goto err_apply;
1588 }
1589
1590 err_apply:
1591 memset ( &tmp, 0, sizeof ( tmp ) );
1592 return rc;
1593}

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

1606 {
1607 struct digest_algorithm *digest = tlskey->digest;
1608 size_t digestsize = digest->digestsize;
1609 char label[ 16 /* "[client|server] finished" + NUL */ ];
1610
1611 /* Verification data must be at least 12 bytes for all digests */
1612 if ( verify_len < TLSKEY_HASH_VERIFY_MIN )
1613 return -EINVAL;
1614
1615 /* Verification data is derived from the master secret */
1616 if ( ! ( tlskey->kdf.flags & TLSKEY_KDF_MASTER ) ) {
1617 DBGC ( tlskey, "TLSKEY %p cannot generate verification data "
1618 "without a master secret\n", tlskey );
1619 return -EPROTO;
1620 }
1621
1622 /* Construct label */
1623 snprintf ( label, sizeof ( label ), "%s finished", end->name );
1624
1625 /* Generate verification data */
1626 tlskey_expand ( tlskey, tlskey->kdf.secret, label,
1627 tlskey->transcript.running, digestsize,
1628 verify, verify_len );
1629
1630 return 0;
1631}
#define TLSKEY_HASH_VERIFY_MIN
Minimum length for verification data.
Definition tlskey.c:1433

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

1643 {
1644 struct tls_traffic_secret *traffic = &tlskey->traffic[writer->index];
1645
1646 /* Only application phase keys are supported */
1647 if ( phase != &tls_application ) {
1648 DBGC ( tlskey, "TLSKEY %p does not support %s traffic keys\n",
1649 tlskey, phase->name );
1650 return -ENOTSUP;
1651 }
1652
1653 /* There are no separate traffic secrets */
1654 assert ( traffic->secret == tlskey->kdf.secret );
1655
1656 return 0;
1657}

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

1675 {
1676 size_t total = ( 2 * ( mac_len + key_len + iv_len ) );
1677 struct {
1678 uint8_t key[total];
1679 } tmp;
1680 struct {
1681 struct tls_random server;
1682 struct tls_random client;
1683 } __attribute__ (( packed )) seed;
1684 const void *src;
1685 size_t mask;
1686
1687 /* Construct seed (with swapped client/server random bytes) */
1688 memcpy ( &seed.server, &tlskey->random[TLS_SERVER],
1689 sizeof ( seed.server ) );
1690 memcpy ( &seed.client, &tlskey->random[TLS_CLIENT],
1691 sizeof ( seed.client ) );
1692
1693 /* Generate key material */
1694 tlskey_expand ( tlskey, tlskey->kdf.secret, "key expansion", &seed,
1695 sizeof ( seed ), tmp.key, sizeof ( tmp.key ) );
1696
1697 /* Partition key material */
1698 src = tmp.key;
1699 mask = ( ( writer->index == TLS_CLIENT ) ? 0 : -1UL );
1700 memcpy ( mac, ( src + ( mac_len & mask ) ), mac_len );
1701 src += ( 2 * mac_len );
1702 memcpy ( key, ( src + ( key_len & mask ) ), key_len );
1703 src += ( 2 * key_len );
1704 memcpy ( iv, ( src + ( iv_len & mask ) ), iv_len );
1705 src += ( 2 * iv_len );
1706 assert ( src == &tmp.key[total] );
1707
1708 /* Clear temporary secrets */
1709 memset ( &tmp, 0, sizeof ( tmp ) );
1710
1711 return 0;
1712}
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 1725 of file tlskey.c.

1728 {
1729 size_t ctxsize = digest->ctxsize;
1730 struct {
1731 uint8_t ctx[ctxsize];
1732 } tmp;
1733
1734 /* Generate endpoint-specific digest value */
1735 if ( end->index == TLS_CLIENT ) {
1736
1737 /* The client CertificateVerify digest value is the
1738 * raw transcript digest. We retain only a single
1739 * running transcript digest, and can therefore
1740 * provide this only for a digest algorithm that
1741 * matches our transcript digest algorithm.
1742 */
1743 if ( digest != tlskey->digest ) {
1744 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
1745 "transcript digest\n", tlskey, digest->name );
1746 return -ENOTSUP;
1747 }
1748
1749 /* There is no way to incorporate additional data */
1750 if ( len ) {
1751 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1752 "with additional data\n", tlskey );
1753 return -ENOTSUP;
1754 }
1755
1756 /* Copy transcript digest value */
1757 memcpy ( tbs, tlskey->transcript.running,
1758 digest->digestsize );
1759
1760 } else {
1761
1762 /* Additional data (i.e. the ServerKeyExchange
1763 * parameters) must be incorporated, since otherwise
1764 * the digest does not cover the parameters used to
1765 * establish the shared secret.
1766 */
1767 if ( ! len ) {
1768 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
1769 "without additional data\n", tlskey );
1770 return -ENOTSUP;
1771 }
1772
1773 /* Generate ServerKeyExchange digest */
1774 digest_init ( digest, tmp.ctx );
1775 digest_update ( digest, tmp.ctx, &tlskey->random,
1776 sizeof ( tlskey->random ) );
1777 digest_update ( digest, tmp.ctx, data, len );
1778 digest_final ( digest, tmp.ctx, tbs );
1779 }
1780
1781 /* Clear temporary secrets */
1782 memset ( &tmp, 0, sizeof ( tmp ) );
1783
1784 return 0;
1785}

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.

Referenced by tlskey_md5_sha1_tbshash().

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

1798 {
1799 struct digest_algorithm *digest = tlskey->digest;
1800
1801 /* A ticket nonce is not supported */
1802 if ( nonce_len )
1803 return -ENOTSUP;
1804
1805 /* For TLS version 1.2, the pre-master secret may be any
1806 * length but the master secret is fixed at 48 bytes. This is
1807 * smaller than the block size for all supported digest
1808 * algorithms. The HMAC key constructed from the master
1809 * secret will therefore be just the zero-padded master secret
1810 * value. We can therefore preserve just these first 48 bytes
1811 * of the KDF master secret (ignoring the zero padding up to
1812 * the digest block size).
1813 */
1814 assert ( sizeof ( psk->key.master_secret ) <=
1815 hmac_keysize ( digest ) );
1816 memcpy ( &psk->key.master_secret, tlskey->kdf.secret,
1817 sizeof ( psk->key.master_secret ) );
1818
1819 return 0;
1820}
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 1829 of file tlskey.c.

1830 {
1831 const void *secret;
1832 size_t secret_len;
1833 int rc;
1834
1835 /* For TLS versions 1.2 and earlier, the pre-shared key
1836 * material contains the master secret and so we just apply
1837 * this as the key derivation function secret.
1838 */
1839 secret = &psk->key.master_secret;
1840 secret_len = sizeof ( psk->key.master_secret );
1841 if ( ( rc = tlskey_apply ( tlskey, secret, secret_len ) ) != 0 )
1842 return rc;
1843
1844 return 0;
1845}

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

1858 {
1859
1860 /* Binder values are not supported */
1861 if ( binder_len )
1862 return -ENOTSUP;
1863
1864 return 0;
1865}

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

1899 {
1900 struct md5_sha1_hmac_keys *hkeys;
1901 size_t secretsize;
1902
1903 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1904 if ( digest != &md5_sha1_algorithm )
1905 return 0;
1906
1907 /* A P_MD5()+P_SHA1() key is a split HMAC-MD5 and HMAC-SHA1 key */
1908 assert ( sizeof ( hkeys->md5 ) == hmac_keysize ( &md5_algorithm ) );
1909 assert ( sizeof ( hkeys->sha1 ) == hmac_keysize ( &sha1_algorithm ) );
1910 secretsize = sizeof ( *hkeys );
1911
1912 return secretsize;
1913}
struct digest_algorithm md5_algorithm
struct digest_algorithm md5_sha1_algorithm
Hybrid MD5+SHA1 digest algorithm.
Definition md5_sha1.c:87
struct digest_algorithm sha1_algorithm
An MD5+SHA1 HMAC key block.
Definition md5_sha1.h:57
uint8_t md5[MD5_BLOCK_SIZE]
MD5 HMAC key.
Definition md5_sha1.h:59
uint8_t sha1[SHA1_BLOCK_SIZE]
SHA-1 HMAC key.
Definition md5_sha1.h:61

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

◆ tlskey_md5_sha1_expand()

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

Expand key material.

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

Definition at line 1926 of file tlskey.c.

1929 {
1930 const struct md5_sha1_hmac_keys *hkeys = secret;
1931 struct {
1932 uint8_t sha1[out_len];
1933 } tmp;
1934 uint8_t *xor;
1935 unsigned int i;
1936
1937 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1938 assert ( digest == &md5_sha1_algorithm );
1939
1940 /* Generate MD5 portion into output buffer */
1941 tlskey_hash_expand ( &md5_algorithm, hkeys->md5, label, seed,
1942 seed_len, out, out_len );
1943
1944 /* Generate SHA-1 portion into temporary buffer */
1945 tlskey_hash_expand ( &sha1_algorithm, hkeys->sha1, label, seed,
1946 seed_len, tmp.sha1, out_len );
1947
1948 /* XOR together into output buffer */
1949 xor = out;
1950 for ( i = 0 ; i < out_len ; i++ )
1951 xor[i] ^= tmp.sha1[i];
1952
1953 /* Clear temporary secrets */
1954 memset ( &tmp, 0, sizeof ( tmp ) );
1955}
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:1458

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

1966 {
1967 struct digest_algorithm *digest = tlskey->digest;
1968 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
1969 size_t hctxsize = hmac_ctxsize ( digest );
1970 struct {
1971 uint8_t hctx[hctxsize];
1972 } tmp;
1973 const void *shared_md5;
1974 const void *shared_sha1;
1975 size_t shared_sublen;
1976
1977 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
1978 assert ( digest == &md5_sha1_algorithm );
1979
1980 /* Split secret into two, with an overlap of up to one byte */
1981 shared_sublen = ( ( shared_len + 1 ) / 2 );
1982 shared_md5 = shared;
1983 shared_sha1 = ( shared + shared_len - shared_sublen );
1984
1985 /* Set HMAC-MD5 key */
1986 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &md5_algorithm ) );
1987 hmac_key ( &md5_algorithm, tmp.hctx, shared_md5, shared_sublen,
1988 hkeys->md5 );
1989
1990 /* Set HMAC-SHA1 key */
1991 assert ( sizeof ( tmp.hctx ) >= hmac_ctxsize ( &sha1_algorithm ) );
1992 hmac_key ( &sha1_algorithm, tmp.hctx, shared_sha1, shared_sublen,
1993 hkeys->sha1 );
1994
1995 /* Clear temporary secrets */
1996 memset ( &tmp, 0, sizeof ( tmp ) );
1997
1998 return 0;
1999}

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_tbshash()

int tlskey_md5_sha1_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 2012 of file tlskey.c.

2016 {
2017 struct md5_sha1_digest *running = tlskey->transcript.running;
2018 const void *hash;
2019
2020 /* The client CertificateVerify digest value is the raw
2021 * transcript digest. We retain an MD5+SHA1 transcript
2022 * digest, which is the concatenation of the MD5 and SHA-1
2023 * transcript digests. We can therefore provide a signable
2024 * digest value for MD5 or SHA-1 as well as for MD5+SHA1.
2025 */
2026 if ( ( end->index == TLS_CLIENT ) && ( digest != tlskey->digest ) ) {
2027
2028 /* Locate MD5 or SHA-1 portion */
2029 if ( digest == &md5_algorithm ) {
2030 hash = running->md5;
2031 } else if ( digest == &sha1_algorithm ) {
2032 hash = running->sha1;
2033 } else {
2034 DBGC ( tlskey, "TLSKEY %p cannot generate %s "
2035 "transcript digest\n", tlskey, digest->name );
2036 return -ENOTSUP;
2037 }
2038
2039 /* There is no way to incorporate additional data */
2040 if ( len ) {
2041 DBGC ( tlskey, "TLSKEY %p cannot generate digest "
2042 "with additional data\n", tlskey );
2043 return -ENOTSUP;
2044 }
2045
2046 /* Copy transcript digest value */
2047 memcpy ( tbs, hash, digest->digestsize );
2048
2049 return 0;
2050 }
2051
2052 /* Otherwise, generate MD5+SHA1 signable digest value */
2053 return tlskey_hash_tbshash ( tlskey, end, digest, data, len, tbs );
2054}
An MD5+SHA1 digest.
Definition md5_sha1.h:30
uint8_t md5[MD5_DIGEST_SIZE]
MD5 digest.
Definition md5_sha1.h:32
uint8_t sha1[SHA1_DIGEST_SIZE]
SHA-1 digest.
Definition md5_sha1.h:34
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:1725

References data, DBGC, tls_key_schedule::digest, digest_algorithm::digestsize, end, ENOTSUP, hash, len, md5_sha1_digest::md5, md5_algorithm, memcpy(), digest_algorithm::name, tls_transcript::running, md5_sha1_digest::sha1, sha1_algorithm, TLS_CLIENT, tlskey_hash_tbshash(), and tls_key_schedule::transcript.

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

2068 {
2069 struct digest_algorithm *digest = tlskey->digest;
2070 struct md5_sha1_hmac_keys *hkeys = tlskey->kdf.secret;
2071
2072 /* P_MD5()+P_SHA1() can be used only with the MD5+SHA1 algorithm */
2073 assert ( digest == &md5_sha1_algorithm );
2074
2075 /* A ticket nonce is not supported */
2076 if ( nonce_len )
2077 return -ENOTSUP;
2078
2079 /* For TLS versions 1.1 and earlier, the pre-master secret may
2080 * be any length but the master secret is fixed at 48 bytes.
2081 * It will have been split to become 24 bytes in each of the
2082 * MD5 and SHA-1 HMAC keys.
2083 */
2084 assert ( sizeof ( psk->key.master_secret.md5 ) <=
2086 assert ( sizeof ( psk->key.master_secret.sha1 ) <=
2088 memcpy ( psk->key.master_secret.md5, hkeys->md5,
2089 sizeof ( psk->key.master_secret.md5 ) );
2090 memcpy ( psk->key.master_secret.sha1, hkeys->sha1,
2091 sizeof ( psk->key.master_secret.sha1 ) );
2092
2093 return 0;
2094}
uint8_t md5[24]
Definition tlskey.h:164
uint8_t sha1[24]
Definition tlskey.h:165

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:454
TLS server state.
Definition tls.h:464

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_hrr_test(), rfc8448_resumed_test(), rfc8448_simple_test(), tls_new_server_hello(), and tlskey_hkdf_verify().

◆ tls_application

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

Application traffic phase.

Definition at line 151 of file tlskey.c.

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

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

◆ tlskey_hkdf

const struct tls_key_schedule_operations tlskey_hkdf
Initial value:
= {
.name = "HKDF",
.accumulates = 1,
.secretsize = tlskey_hkdf_secretsize,
.expand = tlskey_hkdf_expand,
.master = tlskey_hkdf_master,
.verify = tlskey_hkdf_verify,
.traffic = tlskey_hkdf_traffic,
.cipher = tlskey_hkdf_cipher,
.tbshash = tlskey_hkdf_tbshash,
}
static int tlskey_hkdf_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1121
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:1220
static void tlskey_hkdf_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1068
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:1151
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:1304
static int tlskey_hkdf_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1342
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:1369
static size_t tlskey_hkdf_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:969
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:1092
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:1263
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:1187

TLS key schedule based on HKDF.

Definition at line 1407 of file tlskey.c.

1407 {
1408 .name = "HKDF",
1409 .accumulates = 1,
1410 .mask = TLSKEY_KDF_KEYED,
1411 .secretsize = tlskey_hkdf_secretsize,
1412 .expand = tlskey_hkdf_expand,
1413 .reset = tlskey_hkdf_reset,
1414 .apply = tlskey_hkdf_apply,
1415 .master = tlskey_hkdf_master,
1416 .verify = tlskey_hkdf_verify,
1417 .traffic = tlskey_hkdf_traffic,
1418 .cipher = tlskey_hkdf_cipher,
1419 .tbshash = tlskey_hkdf_tbshash,
1420 .save = tlskey_hkdf_save,
1421 .load = tlskey_hkdf_load,
1422 .bind = tlskey_hkdf_bind,
1423};

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

◆ tlskey_hash

const struct tls_key_schedule_operations tlskey_hash
Initial value:
= {
.name = "P_Hash()",
.accumulates = 0,
.secretsize = tlskey_hash_secretsize,
.expand = tlskey_hash_expand,
.master = tlskey_hash_master,
.verify = tlskey_hash_verify,
.traffic = tlskey_hash_traffic,
.cipher = tlskey_hash_cipher,
.tbshash = tlskey_hash_tbshash,
}
static int tlskey_hash_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:1672
static int tlskey_hash_load(struct tls_key_schedule *tlskey, const struct tls_preshared_key *psk)
Load pre-shared key.
Definition tlskey.c:1829
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:1604
static int tlskey_hash_master(struct tls_key_schedule *tlskey, int ems)
Generate master secret.
Definition tlskey.c:1551
static void tlskey_hash_reset(struct tls_key_schedule *tlskey)
Reset key schedule.
Definition tlskey.c:1510
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:1641
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:1796
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:1856
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:1527
static size_t tlskey_hash_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1441

TLS key schedule based on P_Hash().

Definition at line 1868 of file tlskey.c.

1868 {
1869 .name = "P_Hash()",
1870 .accumulates = 0,
1872 .secretsize = tlskey_hash_secretsize,
1873 .expand = tlskey_hash_expand,
1874 .reset = tlskey_hash_reset,
1875 .apply = tlskey_hash_apply,
1876 .master = tlskey_hash_master,
1877 .verify = tlskey_hash_verify,
1878 .traffic = tlskey_hash_traffic,
1879 .cipher = tlskey_hash_cipher,
1880 .tbshash = tlskey_hash_tbshash,
1881 .save = tlskey_hash_save,
1882 .load = tlskey_hash_load,
1883 .bind = tlskey_hash_bind,
1884};

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,
}
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:1926
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:2065
static size_t tlskey_md5_sha1_secretsize(struct digest_algorithm *digest)
Calculate secret size.
Definition tlskey.c:1899
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:1965
static int tlskey_md5_sha1_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:2012

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

Definition at line 2097 of file tlskey.c.

2097 {
2098 .name = "P_MD5()+P_SHA1()",
2099 .accumulates = 0,
2101 .secretsize = tlskey_md5_sha1_secretsize,
2102 .expand = tlskey_md5_sha1_expand,
2103 .reset = tlskey_hash_reset,
2104 .apply = tlskey_md5_sha1_apply,
2105 .master = tlskey_hash_master,
2106 .verify = tlskey_hash_verify,
2107 .traffic = tlskey_hash_traffic,
2108 .cipher = tlskey_hash_cipher,
2109 .tbshash = tlskey_md5_sha1_tbshash,
2110 .save = tlskey_md5_sha1_save,
2111 .load = tlskey_hash_load,
2112 .bind = tlskey_hash_bind,
2113};

Referenced by dummy_md5_sha1(), and tls_set_digest().