Coverage Report

Created: 2025-06-24 06:49

/src/nss/lib/ssl/tls13subcerts.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/*
3
 * This Source Code Form is subject to the terms of the Mozilla Public
4
 * License, v. 2.0. If a copy of the MPL was not distributed with this
5
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7
#include "nss.h"
8
#include "pk11func.h"
9
#include "secder.h"
10
#include "sechash.h"
11
#include "ssl.h"
12
#include "sslproto.h"
13
#include "sslimpl.h"
14
#include "ssl3exthandle.h"
15
#include "tls13exthandle.h"
16
#include "tls13hkdf.h"
17
#include "tls13subcerts.h"
18
19
/* Parses the delegated credential (DC) from the raw extension |b| of length
20
 * |length|. Memory for the DC is allocated and set to |*dcp|.
21
 *
22
 * It's the caller's responsibility to invoke |tls13_DestroyDelegatedCredential|
23
 * when this data is no longer needed.
24
 */
25
SECStatus
26
tls13_ReadDelegatedCredential(PRUint8 *b, PRUint32 length,
27
                              sslDelegatedCredential **dcp)
28
0
{
29
0
    sslDelegatedCredential *dc = NULL;
30
0
    SECStatus rv;
31
0
    PRUint64 n;
32
0
    sslReadBuffer tmp;
33
0
    sslReader rdr = SSL_READER(b, length);
34
35
0
    PORT_Assert(!*dcp);
36
37
0
    dc = PORT_ZNew(sslDelegatedCredential);
38
0
    if (!dc) {
39
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
40
0
        goto loser;
41
0
    }
42
43
    /* Read the valid_time field of DelegatedCredential.cred. */
44
0
    rv = sslRead_ReadNumber(&rdr, 4, &n);
45
0
    if (rv != SECSuccess) {
46
0
        goto loser;
47
0
    }
48
0
    dc->validTime = n;
49
50
    /* Read the expected_cert_verify_algorithm field of
51
     * DelegatedCredential.cred. */
52
0
    rv = sslRead_ReadNumber(&rdr, 2, &n);
53
0
    if (rv != SECSuccess) {
54
0
        goto loser;
55
0
    }
56
0
    dc->expectedCertVerifyAlg = n;
57
58
    /* Read the ASN1_subjectPublicKeyInfo field of DelegatedCredential.cred. */
59
0
    rv = sslRead_ReadVariable(&rdr, 3, &tmp);
60
0
    if (rv != SECSuccess) {
61
0
        goto loser;
62
0
    }
63
0
    rv = SECITEM_MakeItem(NULL, &dc->derSpki, tmp.buf, tmp.len);
64
0
    if (rv != SECSuccess) {
65
0
        goto loser;
66
0
    }
67
68
    /* Parse the DER-encoded SubjectPublicKeyInfo. */
69
0
    dc->spki = SECKEY_DecodeDERSubjectPublicKeyInfo(&dc->derSpki);
70
0
    if (!dc->spki) {
71
0
        goto loser;
72
0
    }
73
74
    /* Read the algorithm field of the DelegatedCredential. */
75
0
    rv = sslRead_ReadNumber(&rdr, 2, &n);
76
0
    if (rv != SECSuccess) {
77
0
        goto loser;
78
0
    }
79
0
    dc->alg = n;
80
81
    /* Read the signature field of the DelegatedCredential. */
82
0
    rv = sslRead_ReadVariable(&rdr, 2, &tmp);
83
0
    if (rv != SECSuccess) {
84
0
        goto loser;
85
0
    }
86
0
    rv = SECITEM_MakeItem(NULL, &dc->signature, tmp.buf, tmp.len);
87
0
    if (rv != SECSuccess) {
88
0
        goto loser;
89
0
    }
90
91
    /* There should be nothing left to read. */
92
0
    if (SSL_READER_REMAINING(&rdr) > 0) {
93
0
        goto loser;
94
0
    }
95
96
0
    *dcp = dc;
97
0
    return SECSuccess;
98
99
0
loser:
100
0
    tls13_DestroyDelegatedCredential(dc);
101
0
    *dcp = NULL;
102
0
    return SECFailure;
103
0
}
104
105
/* Frees |dc| from the heap. */
106
void
107
tls13_DestroyDelegatedCredential(sslDelegatedCredential *dc)
108
354k
{
109
354k
    if (!dc) {
110
354k
        return;
111
354k
    }
112
113
0
    SECKEY_DestroySubjectPublicKeyInfo(dc->spki);
114
0
    SECITEM_FreeItem(&dc->derSpki, PR_FALSE);
115
0
    SECITEM_FreeItem(&dc->signature, PR_FALSE);
116
0
    PORT_ZFree(dc, sizeof(sslDelegatedCredential));
117
0
}
118
119
/* Sets |*certVerifyAlg| to the expected_cert_verify_algorithm field from the
120
 * serialized DC |in|. Returns SECSuccess upon success; SECFailure indicates a
121
 * decoding failure or the input wasn't long enough.
122
 */
123
static SECStatus
124
tls13_GetExpectedCertVerifyAlg(SECItem in, SSLSignatureScheme *certVerifyAlg)
125
0
{
126
0
    SECStatus rv;
127
0
    PRUint64 n;
128
0
    sslReader rdr = SSL_READER(in.data, in.len);
129
130
0
    if (in.len < 6) { /* Buffer too short to contain the first two params. */
131
0
        return SECFailure;
132
0
    }
133
134
0
    rv = sslRead_ReadNumber(&rdr, 4, &n);
135
0
    if (rv != SECSuccess) {
136
0
        return SECFailure;
137
0
    }
138
139
0
    rv = sslRead_ReadNumber(&rdr, 2, &n);
140
0
    if (rv != SECSuccess) {
141
0
        return SECFailure;
142
0
    }
143
0
    *certVerifyAlg = n;
144
145
0
    return SECSuccess;
146
0
}
147
148
/* Returns PR_TRUE if the host is verifying the handshake with a DC. */
149
PRBool
150
tls13_IsVerifyingWithDelegatedCredential(const sslSocket *ss)
151
0
{
152
    /* We currently do not support client-delegated credentials. */
153
0
    if (ss->sec.isServer ||
154
0
        !ss->opt.enableDelegatedCredentials ||
155
0
        !ss->xtnData.peerDelegCred) {
156
0
        return PR_FALSE;
157
0
    }
158
159
0
    return PR_TRUE;
160
0
}
161
162
/* Returns PR_TRUE if the host is signing the handshake with a DC. */
163
PRBool
164
tls13_IsSigningWithDelegatedCredential(const sslSocket *ss)
165
2.40k
{
166
2.40k
    if (!ss->sec.isServer ||
167
2.40k
        !ss->xtnData.sendingDelegCredToPeer ||
168
2.40k
        !ss->xtnData.peerRequestedDelegCred) {
169
2.40k
        return PR_FALSE;
170
2.40k
    }
171
172
0
    return PR_TRUE;
173
2.40k
}
174
175
/* Commits to authenticating with a DC if all of the following conditions hold:
176
 *  - the negotiated protocol is TLS 1.3 or newer;
177
 *  - the selected certificate has a DC configured;
178
 *  - the peer has indicated support for this extension;
179
 *  - the peer has indicated support for the DC signature scheme; and
180
 *  - the host supports the DC signature scheme.
181
 *
182
 * It's the caller's responsibility to ensure that the version has been
183
 * negotiated and the certificate has been selected.
184
 */
185
SECStatus
186
tls13_MaybeSetDelegatedCredential(sslSocket *ss)
187
2.51k
{
188
2.51k
    SECStatus rv;
189
2.51k
    PRBool doesRsaPss;
190
2.51k
    SECKEYPrivateKey *priv;
191
2.51k
    SSLSignatureScheme scheme;
192
193
    /* Assert that the host is the server (we do not currently support
194
     * client-delegated credentials), the certificate has been
195
     * chosen, TLS 1.3 or higher has been negotiated, and that the set of
196
     * signature schemes supported by the client is known.
197
     */
198
2.51k
    PORT_Assert(ss->sec.isServer);
199
2.51k
    PORT_Assert(ss->sec.serverCert);
200
2.51k
    PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_TLS_1_3);
201
2.51k
    PORT_Assert(ss->xtnData.peerRequestedDelegCred == !!ss->xtnData.delegCredSigSchemes);
202
203
    /* Check that the peer has indicated support and that a DC has been
204
     * configured for the selected certificate.
205
     */
206
2.51k
    if (!ss->xtnData.peerRequestedDelegCred ||
207
2.51k
        !ss->xtnData.delegCredSigSchemes ||
208
2.51k
        !ss->sec.serverCert->delegCred.len ||
209
2.51k
        !ss->sec.serverCert->delegCredKeyPair) {
210
2.51k
        return SECSuccess;
211
2.51k
    }
212
213
    /* Check that the host and peer both support the signing algorithm used with
214
     * the DC.
215
     */
216
0
    rv = tls13_GetExpectedCertVerifyAlg(ss->sec.serverCert->delegCred,
217
0
                                        &scheme);
218
0
    if (rv != SECSuccess) {
219
0
        return SECFailure;
220
0
    }
221
222
0
    priv = ss->sec.serverCert->delegCredKeyPair->privKey;
223
0
    rv = ssl_PrivateKeySupportsRsaPss(priv, NULL, NULL, &doesRsaPss);
224
0
    if (rv != SECSuccess) {
225
0
        return SECFailure;
226
0
    }
227
228
0
    if (!ssl_SignatureSchemeEnabled(ss, scheme) ||
229
0
        !ssl_CanUseSignatureScheme(scheme,
230
0
                                   ss->xtnData.delegCredSigSchemes,
231
0
                                   ss->xtnData.numDelegCredSigSchemes,
232
0
                                   PR_FALSE /* requireSha1 */,
233
0
                                   doesRsaPss)) {
234
0
        return SECSuccess;
235
0
    }
236
237
    /* Commit to sending a DC and set the handshake signature scheme to the
238
     * indicated algorithm.
239
     */
240
0
    ss->xtnData.sendingDelegCredToPeer = PR_TRUE;
241
0
    ss->ssl3.hs.signatureScheme = scheme;
242
0
    return SECSuccess;
243
0
}
244
245
/* Serializes the DC up to the signature. */
246
static SECStatus
247
tls13_AppendCredentialParams(sslBuffer *buf, sslDelegatedCredential *dc)
248
0
{
249
0
    SECStatus rv;
250
0
    rv = sslBuffer_AppendNumber(buf, dc->validTime, 4);
251
0
    if (rv != SECSuccess) {
252
0
        return SECFailure; /* Error set by caller. */
253
0
    }
254
255
0
    rv = sslBuffer_AppendNumber(buf, dc->expectedCertVerifyAlg, 2);
256
0
    if (rv != SECSuccess) {
257
0
        return SECFailure;
258
0
    }
259
260
0
    rv = sslBuffer_AppendVariable(buf, dc->derSpki.data, dc->derSpki.len, 3);
261
0
    if (rv != SECSuccess) {
262
0
        return SECFailure;
263
0
    }
264
265
0
    rv = sslBuffer_AppendNumber(buf, dc->alg, 2);
266
0
    if (rv != SECSuccess) {
267
0
        return SECFailure;
268
0
    }
269
270
0
    return SECSuccess;
271
0
}
272
273
/* Serializes the DC signature. */
274
static SECStatus
275
tls13_AppendCredentialSignature(sslBuffer *buf, sslDelegatedCredential *dc)
276
0
{
277
0
    SECStatus rv;
278
0
    rv = sslBuffer_AppendVariable(buf, dc->signature.data,
279
0
                                  dc->signature.len, 2);
280
0
    if (rv != SECSuccess) {
281
0
        return SECFailure;
282
0
    }
283
284
0
    return SECSuccess;
285
0
}
286
287
/* Hashes the message used to sign/verify the DC. */
288
static SECStatus
289
tls13_HashCredentialSignatureMessage(SSL3Hashes *hash,
290
                                     SSLSignatureScheme scheme,
291
                                     const CERTCertificate *cert,
292
                                     const sslBuffer *dcBuf)
293
0
{
294
0
    SECStatus rv;
295
0
    PK11Context *ctx = NULL;
296
0
    unsigned int hashLen;
297
298
    /* Set up hash context. */
299
0
    hash->hashAlg = ssl_SignatureSchemeToHashType(scheme);
300
0
    ctx = PK11_CreateDigestContext(ssl3_HashTypeToOID(hash->hashAlg));
301
0
    if (!ctx) {
302
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
303
0
        goto loser;
304
0
    }
305
306
0
    static const PRUint8 kCtxStrPadding[64] = {
307
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
308
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
309
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
310
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
311
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
312
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
313
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
314
0
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20
315
0
    };
316
317
0
    static const PRUint8 kCtxStr[] = "TLS, server delegated credentials";
318
319
    /* Hash the message signed by the peer. */
320
0
    rv = SECSuccess;
321
0
    rv |= PK11_DigestBegin(ctx);
322
0
    rv |= PK11_DigestOp(ctx, kCtxStrPadding, sizeof kCtxStrPadding);
323
0
    rv |= PK11_DigestOp(ctx, kCtxStr, 1 /* 0-byte */ + strlen((const char *)kCtxStr));
324
0
    rv |= PK11_DigestOp(ctx, cert->derCert.data, cert->derCert.len);
325
0
    rv |= PK11_DigestOp(ctx, dcBuf->buf, dcBuf->len);
326
0
    rv |= PK11_DigestFinal(ctx, hash->u.raw, &hashLen, sizeof hash->u.raw);
327
0
    if (rv != SECSuccess) {
328
0
        PORT_SetError(SSL_ERROR_SHA_DIGEST_FAILURE);
329
0
        goto loser;
330
0
    }
331
332
0
    hash->len = hashLen;
333
0
    if (ctx) {
334
0
        PK11_DestroyContext(ctx, PR_TRUE);
335
0
    }
336
0
    return SECSuccess;
337
338
0
loser:
339
0
    if (ctx) {
340
0
        PK11_DestroyContext(ctx, PR_TRUE);
341
0
    }
342
0
    return SECFailure;
343
0
}
344
345
/* Verifies the DC signature. */
346
static SECStatus
347
tls13_VerifyCredentialSignature(sslSocket *ss, sslDelegatedCredential *dc)
348
0
{
349
0
    SECStatus rv = SECSuccess;
350
0
    SSL3Hashes hash;
351
0
    sslBuffer dcBuf = SSL_BUFFER_EMPTY;
352
0
    CERTCertificate *cert = ss->sec.peerCert;
353
0
    SECKEYPublicKey *pubKey = NULL;
354
355
    /* Serialize the DC parameters. */
356
0
    rv = tls13_AppendCredentialParams(&dcBuf, dc);
357
0
    if (rv != SECSuccess) {
358
0
        goto loser; /* Error set by caller. */
359
0
    }
360
361
    /* Hash the message that was signed by the delegator. */
362
0
    rv = tls13_HashCredentialSignatureMessage(&hash, dc->alg, cert, &dcBuf);
363
0
    if (rv != SECSuccess) {
364
0
        FATAL_ERROR(ss, PORT_GetError(), internal_error);
365
0
        goto loser;
366
0
    }
367
368
0
    pubKey = SECKEY_ExtractPublicKey(&cert->subjectPublicKeyInfo);
369
0
    if (pubKey == NULL) {
370
0
        FATAL_ERROR(ss, SSL_ERROR_EXTRACT_PUBLIC_KEY_FAILURE, internal_error);
371
0
        goto loser;
372
0
    }
373
374
    /* Verify the signature of the message. */
375
0
    rv = ssl_VerifySignedHashesWithPubKey(ss, pubKey, dc->alg,
376
0
                                          &hash, &dc->signature);
377
0
    if (rv != SECSuccess) {
378
0
        FATAL_ERROR(ss, SSL_ERROR_DC_BAD_SIGNATURE, illegal_parameter);
379
0
        goto loser;
380
0
    }
381
382
0
    SECOidTag spkiAlg = SECOID_GetAlgorithmTag(&(dc->spki->algorithm));
383
0
    if (spkiAlg == SEC_OID_PKCS1_RSA_ENCRYPTION) {
384
0
        FATAL_ERROR(ss, SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM, illegal_parameter);
385
0
        goto loser;
386
0
    }
387
388
0
    SECKEY_DestroyPublicKey(pubKey);
389
0
    sslBuffer_Clear(&dcBuf);
390
0
    return SECSuccess;
391
392
0
loser:
393
0
    SECKEY_DestroyPublicKey(pubKey);
394
0
    sslBuffer_Clear(&dcBuf);
395
0
    return SECFailure;
396
0
}
397
398
/* Checks that the peer's end-entity certificate has the correct key usage. */
399
static SECStatus
400
tls13_CheckCertDelegationUsage(sslSocket *ss)
401
0
{
402
0
    int i;
403
0
    PRBool found;
404
0
    CERTCertExtension *ext;
405
0
    SECItem delegUsageOid = { siBuffer, NULL, 0 };
406
0
    const CERTCertificate *cert = ss->sec.peerCert;
407
408
    /* 1.3.6.1.4.1.44363.44, as defined in draft-ietf-tls-subcerts. */
409
0
    static unsigned char kDelegationUsageOid[] = {
410
0
        0x2b,
411
0
        0x06,
412
0
        0x01,
413
0
        0x04,
414
0
        0x01,
415
0
        0x82,
416
0
        0xda,
417
0
        0x4b,
418
0
        0x2c
419
0
    };
420
421
0
    delegUsageOid.data = kDelegationUsageOid;
422
0
    delegUsageOid.len = sizeof kDelegationUsageOid;
423
424
    /* The certificate must have the delegationUsage extension that authorizes
425
     * it to negotiate delegated credentials.
426
     */
427
0
    found = PR_FALSE;
428
0
    for (i = 0; cert->extensions[i] != NULL; i++) {
429
0
        ext = cert->extensions[i];
430
0
        if (SECITEM_CompareItem(&ext->id, &delegUsageOid) == SECEqual) {
431
0
            found = PR_TRUE;
432
0
            break;
433
0
        }
434
0
    }
435
436
    /* The certificate must also have the digitalSignature keyUsage set. */
437
0
    if (!found ||
438
0
        !cert->keyUsagePresent ||
439
0
        !(cert->keyUsage & KU_DIGITAL_SIGNATURE)) {
440
0
        FATAL_ERROR(ss, SSL_ERROR_DC_INVALID_KEY_USAGE, illegal_parameter);
441
0
        return SECFailure;
442
0
    }
443
444
0
    return SECSuccess;
445
0
}
446
447
static SECStatus
448
tls13_CheckCredentialExpiration(sslSocket *ss, sslDelegatedCredential *dc)
449
0
{
450
0
    SECStatus rv;
451
0
    CERTCertificate *cert = ss->sec.peerCert;
452
    /* 7 days in microseconds */
453
0
    static const PRTime kMaxDcValidity = ((PRTime)7 * 24 * 60 * 60 * PR_USEC_PER_SEC);
454
0
    PRTime start, now, end; /* microseconds */
455
456
0
    rv = DER_DecodeTimeChoice(&start, &cert->validity.notBefore);
457
0
    if (rv != SECSuccess) {
458
0
        FATAL_ERROR(ss, PORT_GetError(), internal_error);
459
0
        return SECFailure;
460
0
    }
461
462
0
    end = start + ((PRTime)dc->validTime * PR_USEC_PER_SEC);
463
0
    now = ssl_Time(ss);
464
0
    if (now > end || end < 0) {
465
0
        FATAL_ERROR(ss, SSL_ERROR_DC_EXPIRED, illegal_parameter);
466
0
        return SECFailure;
467
0
    }
468
469
    /* Not more than 7 days remaining in the validity period. */
470
0
    if (end - now > kMaxDcValidity) {
471
0
        FATAL_ERROR(ss, SSL_ERROR_DC_INAPPROPRIATE_VALIDITY_PERIOD, illegal_parameter);
472
0
        return SECFailure;
473
0
    }
474
475
0
    return SECSuccess;
476
0
}
477
478
/* Returns SECSucces if |dc| is a DC for the current handshake; otherwise it
479
 * returns SECFailure. A valid DC meets three requirements: (1) the signature
480
 * was produced by the peer's end-entity certificate, (2) the end-entity
481
 * certificate must have the correct key usage, and (3) the DC must not be
482
 * expired and its remaining TTL must be <= the maximum validity period (fixed
483
 * as 7 days).
484
 *
485
 * This function calls FATAL_ERROR() when an error occurs.
486
 */
487
SECStatus
488
tls13_VerifyDelegatedCredential(sslSocket *ss,
489
                                sslDelegatedCredential *dc)
490
0
{
491
0
    SECStatus rv;
492
0
    PRTime start;
493
0
    PRExplodedTime end;
494
0
    CERTCertificate *cert = ss->sec.peerCert;
495
0
    char endStr[256];
496
497
0
    rv = DER_DecodeTimeChoice(&start, &cert->validity.notBefore);
498
0
    if (rv != SECSuccess) {
499
0
        FATAL_ERROR(ss, PORT_GetError(), internal_error);
500
0
        return SECFailure;
501
0
    }
502
503
0
    PR_ExplodeTime(start + (dc->validTime * PR_USEC_PER_SEC),
504
0
                   PR_GMTParameters, &end);
505
0
    if (PR_FormatTime(endStr, sizeof(endStr), "%a %b %d %H:%M:%S %Y", &end)) {
506
0
        SSL_TRC(20, ("%d: TLS13[%d]: Received delegated credential (expires %s)",
507
0
                     SSL_GETPID(), ss->fd, endStr));
508
0
    } else {
509
0
        SSL_TRC(20, ("%d: TLS13[%d]: Received delegated credential",
510
0
                     SSL_GETPID(), ss->fd));
511
0
    }
512
513
0
    rv = SECSuccess;
514
0
    rv |= tls13_VerifyCredentialSignature(ss, dc);
515
0
    rv |= tls13_CheckCertDelegationUsage(ss);
516
0
    rv |= tls13_CheckCredentialExpiration(ss, dc);
517
0
    return rv;
518
0
}
519
520
static CERTSubjectPublicKeyInfo *
521
tls13_MakePssSpki(const SECKEYPublicKey *pub, SECOidTag hashOid)
522
0
{
523
0
    SECStatus rv;
524
0
    PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
525
0
    if (!arena) {
526
0
        goto loser; /* Code already set. */
527
0
    }
528
0
    CERTSubjectPublicKeyInfo *spki = PORT_ArenaZNew(arena, CERTSubjectPublicKeyInfo);
529
0
    if (!spki) {
530
0
        goto loser; /* Code already set. */
531
0
    }
532
0
    spki->arena = arena;
533
534
0
    SECKEYRSAPSSParams params = { 0 };
535
0
    params.hashAlg = PORT_ArenaZNew(arena, SECAlgorithmID);
536
0
    rv = SECOID_SetAlgorithmID(arena, params.hashAlg, hashOid, NULL);
537
0
    if (rv != SECSuccess) {
538
0
        goto loser; /* Code already set. */
539
0
    }
540
541
    /* Set the mask hash algorithm too, which is an argument to
542
     * a SEC_OID_PKCS1_MGF1 value. */
543
0
    SECAlgorithmID maskHashAlg;
544
0
    memset(&maskHashAlg, 0, sizeof(maskHashAlg));
545
0
    rv = SECOID_SetAlgorithmID(arena, &maskHashAlg, hashOid, NULL);
546
0
    if (rv != SECSuccess) {
547
0
        goto loser; /* Code already set. */
548
0
    }
549
0
    SECItem *maskHashAlgItem =
550
0
        SEC_ASN1EncodeItem(arena, NULL, &maskHashAlg,
551
0
                           SEC_ASN1_GET(SECOID_AlgorithmIDTemplate));
552
0
    if (!maskHashAlgItem) {
553
        /* Probably OOM, but not certain. */
554
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
555
0
        goto loser;
556
0
    }
557
558
0
    params.maskAlg = PORT_ArenaZNew(arena, SECAlgorithmID);
559
0
    rv = SECOID_SetAlgorithmID(arena, params.maskAlg, SEC_OID_PKCS1_MGF1,
560
0
                               maskHashAlgItem);
561
0
    if (rv != SECSuccess) {
562
0
        goto loser; /* Code already set. */
563
0
    }
564
565
    /* Always include saltLength: all hashes are larger than 20. */
566
0
    unsigned int saltLength = HASH_ResultLenByOidTag(hashOid);
567
0
    PORT_Assert(saltLength > 20);
568
0
    if (!SEC_ASN1EncodeInteger(arena, &params.saltLength, saltLength)) {
569
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
570
0
        goto loser;
571
0
    }
572
    /* Omit the trailerField always. */
573
574
0
    SECItem *algorithmItem =
575
0
        SEC_ASN1EncodeItem(arena, NULL, &params,
576
0
                           SEC_ASN1_GET(SECKEY_RSAPSSParamsTemplate));
577
0
    if (!algorithmItem) {
578
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
579
0
        goto loser; /* Code already set. */
580
0
    }
581
0
    rv = SECOID_SetAlgorithmID(arena, &spki->algorithm,
582
0
                               SEC_OID_PKCS1_RSA_PSS_SIGNATURE, algorithmItem);
583
0
    if (rv != SECSuccess) {
584
0
        goto loser; /* Code already set. */
585
0
    }
586
587
0
    SECItem *pubItem = SEC_ASN1EncodeItem(arena, &spki->subjectPublicKey, pub,
588
0
                                          SEC_ASN1_GET(SECKEY_RSAPublicKeyTemplate));
589
0
    if (!pubItem) {
590
0
        PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
591
0
        goto loser;
592
0
    }
593
0
    spki->subjectPublicKey.len *= 8; /* Key length is in bits. */
594
0
    return spki;
595
596
0
loser:
597
0
    PORT_FreeArena(arena, PR_FALSE);
598
0
    return NULL;
599
0
}
600
601
static CERTSubjectPublicKeyInfo *
602
tls13_MakeDcSpki(const SECKEYPublicKey *dcPub, SSLSignatureScheme dcCertVerifyAlg)
603
0
{
604
0
    switch (SECKEY_GetPublicKeyType(dcPub)) {
605
0
        case rsaKey: {
606
0
            SECOidTag hashOid;
607
0
            switch (dcCertVerifyAlg) {
608
                /* Note: RSAE schemes are NOT permitted within DC SPKIs. However,
609
                 * support for their issuance remains so as to enable negative
610
                 * testing of client behavior. */
611
0
                case ssl_sig_rsa_pss_rsae_sha256:
612
0
                case ssl_sig_rsa_pss_rsae_sha384:
613
0
                case ssl_sig_rsa_pss_rsae_sha512:
614
0
                    return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
615
0
                case ssl_sig_rsa_pss_pss_sha256:
616
0
                    hashOid = SEC_OID_SHA256;
617
0
                    break;
618
0
                case ssl_sig_rsa_pss_pss_sha384:
619
0
                    hashOid = SEC_OID_SHA384;
620
0
                    break;
621
0
                case ssl_sig_rsa_pss_pss_sha512:
622
0
                    hashOid = SEC_OID_SHA512;
623
0
                    break;
624
625
0
                default:
626
0
                    PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
627
0
                    return NULL;
628
0
            }
629
0
            return tls13_MakePssSpki(dcPub, hashOid);
630
0
        }
631
632
0
        case ecKey: {
633
0
            const sslNamedGroupDef *group = ssl_ECPubKey2NamedGroup(dcPub);
634
0
            if (!group) {
635
0
                PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
636
0
                return NULL;
637
0
            }
638
0
            SSLSignatureScheme keyScheme;
639
0
            switch (group->name) {
640
0
                case ssl_grp_ec_secp256r1:
641
0
                    keyScheme = ssl_sig_ecdsa_secp256r1_sha256;
642
0
                    break;
643
0
                case ssl_grp_ec_secp384r1:
644
0
                    keyScheme = ssl_sig_ecdsa_secp384r1_sha384;
645
0
                    break;
646
0
                case ssl_grp_ec_secp521r1:
647
0
                    keyScheme = ssl_sig_ecdsa_secp521r1_sha512;
648
0
                    break;
649
0
                default:
650
0
                    PORT_SetError(SEC_ERROR_INVALID_KEY);
651
0
                    return NULL;
652
0
            }
653
0
            if (keyScheme != dcCertVerifyAlg) {
654
0
                PORT_SetError(SSL_ERROR_INCORRECT_SIGNATURE_ALGORITHM);
655
0
                return NULL;
656
0
            }
657
0
            return SECKEY_CreateSubjectPublicKeyInfo(dcPub);
658
0
        }
659
660
0
        default:
661
0
            break;
662
0
    }
663
664
0
    PORT_SetError(SEC_ERROR_INVALID_KEY);
665
0
    return NULL;
666
0
}
667
668
/* Returns a serialized DC with the given parameters.
669
 *
670
 * Note that this function is meant primarily for testing. In particular, it
671
 * DOES NOT verify any of the following:
672
 *  - |certPriv| is the private key corresponding to |cert|;
673
 *  - that |checkCertKeyUsage(cert) == SECSuccess|;
674
 *  - |dcValidFor| is less than 7 days (the maximum permitted by the spec); or
675
 *  - validTime doesn't overflow a PRUint32.
676
 *
677
 * These conditions are things we want to test for, which is why we allow them
678
 * here. A real API for creating DCs would want to explicitly check ALL of these
679
 * conditions are met.
680
 */
681
SECStatus
682
SSLExp_DelegateCredential(const CERTCertificate *cert,
683
                          const SECKEYPrivateKey *certPriv,
684
                          const SECKEYPublicKey *dcPub,
685
                          SSLSignatureScheme dcCertVerifyAlg,
686
                          PRUint32 dcValidFor,
687
                          PRTime now,
688
                          SECItem *out)
689
0
{
690
0
    SECStatus rv;
691
0
    SSL3Hashes hash;
692
0
    CERTSubjectPublicKeyInfo *spki = NULL;
693
0
    SECKEYPrivateKey *tmpPriv = NULL;
694
0
    sslDelegatedCredential *dc = NULL;
695
0
    sslBuffer dcBuf = SSL_BUFFER_EMPTY;
696
697
0
    if (!cert || !certPriv || !dcPub || !out) {
698
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
699
0
        return SECFailure;
700
0
    }
701
702
0
    dc = PORT_ZNew(sslDelegatedCredential);
703
0
    if (!dc) {
704
0
        PORT_SetError(SEC_ERROR_NO_MEMORY);
705
0
        goto loser;
706
0
    }
707
708
    /* Serialize the DC parameters. */
709
0
    PRTime start;
710
0
    rv = DER_DecodeTimeChoice(&start, &cert->validity.notBefore);
711
0
    if (rv != SECSuccess) {
712
0
        goto loser;
713
0
    }
714
0
    dc->validTime = ((now - start) / PR_USEC_PER_SEC) + dcValidFor;
715
716
    /* Building the SPKI also validates |dcCertVerifyAlg|. */
717
0
    spki = tls13_MakeDcSpki(dcPub, dcCertVerifyAlg);
718
0
    if (!spki) {
719
0
        goto loser;
720
0
    }
721
0
    dc->expectedCertVerifyAlg = dcCertVerifyAlg;
722
723
0
    SECItem *spkiDer =
724
0
        SEC_ASN1EncodeItem(NULL /*arena*/, &dc->derSpki, spki,
725
0
                           SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate));
726
0
    if (!spkiDer) {
727
0
        goto loser;
728
0
    }
729
730
0
    rv = ssl_SignatureSchemeFromSpki(&cert->subjectPublicKeyInfo,
731
0
                                     PR_TRUE /* isTls13 */, &dc->alg);
732
0
    if (rv != SECSuccess) {
733
0
        goto loser;
734
0
    }
735
736
0
    if (dc->alg == ssl_sig_none) {
737
0
        SECOidTag spkiOid = SECOID_GetAlgorithmTag(&cert->subjectPublicKeyInfo.algorithm);
738
        /* If the Cert SPKI contained an AlgorithmIdentifier of "rsaEncryption", set a
739
         * default rsa_pss_rsae_sha256 scheme. NOTE: RSAE SPKIs are not permitted within
740
         * "real" Delegated Credentials. However, since this function is primarily used for
741
         * testing, we retain this support in order to verify that these DCs are rejected
742
         * by tls13_VerifyDelegatedCredential. */
743
0
        if (spkiOid == SEC_OID_PKCS1_RSA_ENCRYPTION) {
744
0
            SSLSignatureScheme scheme = ssl_sig_rsa_pss_rsae_sha256;
745
0
            if (ssl_SignatureSchemeValid(scheme, spkiOid, PR_TRUE /* isTls13 */)) {
746
0
                dc->alg = scheme;
747
0
            }
748
0
        }
749
0
    }
750
0
    PORT_Assert(dc->alg != ssl_sig_none);
751
752
0
    rv = tls13_AppendCredentialParams(&dcBuf, dc);
753
0
    if (rv != SECSuccess) {
754
0
        goto loser;
755
0
    }
756
757
    /* Hash signature message. */
758
0
    rv = tls13_HashCredentialSignatureMessage(&hash, dc->alg, cert, &dcBuf);
759
0
    if (rv != SECSuccess) {
760
0
        goto loser;
761
0
    }
762
763
    /* Sign the hash with the delegation key.
764
     *
765
     * The PK11 API discards const qualifiers, so we have to make a copy of
766
     * |certPriv| and pass the copy to |ssl3_SignHashesWithPrivKey|.
767
     */
768
0
    tmpPriv = SECKEY_CopyPrivateKey(certPriv);
769
0
    rv = ssl3_SignHashesWithPrivKey(&hash, tmpPriv, dc->alg,
770
0
                                    PR_TRUE /* isTls */, &dc->signature);
771
0
    if (rv != SECSuccess) {
772
0
        goto loser;
773
0
    }
774
775
    /* Serialize the DC signature. */
776
0
    rv = tls13_AppendCredentialSignature(&dcBuf, dc);
777
0
    if (rv != SECSuccess) {
778
0
        goto loser;
779
0
    }
780
781
    /* Copy the serialized DC to |out|. */
782
0
    rv = SECITEM_MakeItem(NULL, out, dcBuf.buf, dcBuf.len);
783
0
    if (rv != SECSuccess) {
784
0
        goto loser;
785
0
    }
786
787
0
    PRINT_BUF(20, (NULL, "delegated credential", dcBuf.buf, dcBuf.len));
788
789
0
    SECKEY_DestroySubjectPublicKeyInfo(spki);
790
0
    SECKEY_DestroyPrivateKey(tmpPriv);
791
0
    tls13_DestroyDelegatedCredential(dc);
792
0
    sslBuffer_Clear(&dcBuf);
793
0
    return SECSuccess;
794
795
0
loser:
796
0
    SECKEY_DestroySubjectPublicKeyInfo(spki);
797
0
    SECKEY_DestroyPrivateKey(tmpPriv);
798
0
    tls13_DestroyDelegatedCredential(dc);
799
0
    sslBuffer_Clear(&dcBuf);
800
0
    return SECFailure;
801
0
}