Coverage Report

Created: 2024-11-21 07:03

/src/nss-nspr/nss/lib/cryptohi/secvfy.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Verification stuff.
3
 *
4
 * This Source Code Form is subject to the terms of the Mozilla Public
5
 * License, v. 2.0. If a copy of the MPL was not distributed with this
6
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8
#include <stdio.h>
9
#include "cryptohi.h"
10
#include "sechash.h"
11
#include "keyhi.h"
12
#include "secasn1.h"
13
#include "secoid.h"
14
#include "pk11func.h"
15
#include "pkcs1sig.h"
16
#include "secdig.h"
17
#include "secerr.h"
18
#include "keyi.h"
19
#include "nss.h"
20
#include "prenv.h"
21
22
/*
23
** Recover the DigestInfo from an RSA PKCS#1 signature.
24
**
25
** If givenDigestAlg != SEC_OID_UNKNOWN, copy givenDigestAlg to digestAlgOut.
26
** Otherwise, parse the DigestInfo structure and store the decoded digest
27
** algorithm into digestAlgOut.
28
**
29
** Store the encoded DigestInfo into digestInfo.
30
** Store the DigestInfo length into digestInfoLen.
31
**
32
** This function does *not* verify that the AlgorithmIdentifier in the
33
** DigestInfo identifies givenDigestAlg or that the DigestInfo is encoded
34
** correctly; verifyPKCS1DigestInfo does that.
35
**
36
** XXX this is assuming that the signature algorithm has WITH_RSA_ENCRYPTION
37
*/
38
static SECStatus
39
recoverPKCS1DigestInfo(SECOidTag givenDigestAlg,
40
                       /*out*/ SECOidTag *digestAlgOut,
41
                       /*out*/ unsigned char **digestInfo,
42
                       /*out*/ unsigned int *digestInfoLen,
43
                       SECKEYPublicKey *key,
44
                       const SECItem *sig, void *wincx)
45
0
{
46
0
    SGNDigestInfo *di = NULL;
47
0
    SECItem it;
48
0
    PRBool rv = SECSuccess;
49
50
0
    PORT_Assert(digestAlgOut);
51
0
    PORT_Assert(digestInfo);
52
0
    PORT_Assert(digestInfoLen);
53
0
    PORT_Assert(key);
54
0
    PORT_Assert(key->keyType == rsaKey);
55
0
    PORT_Assert(sig);
56
57
0
    it.data = NULL;
58
0
    it.len = SECKEY_PublicKeyStrength(key);
59
0
    if (it.len != 0) {
60
0
        it.data = (unsigned char *)PORT_Alloc(it.len);
61
0
    }
62
0
    if (it.len == 0 || it.data == NULL) {
63
0
        rv = SECFailure;
64
0
    }
65
66
0
    if (rv == SECSuccess) {
67
        /* decrypt the block */
68
0
        rv = PK11_VerifyRecover(key, sig, &it, wincx);
69
0
    }
70
71
0
    if (rv == SECSuccess) {
72
0
        if (givenDigestAlg != SEC_OID_UNKNOWN) {
73
            /* We don't need to parse the DigestInfo if the caller gave us the
74
             * digest algorithm to use. Later verifyPKCS1DigestInfo will verify
75
             * that the DigestInfo identifies the given digest algorithm and
76
             * that the DigestInfo is encoded absolutely correctly.
77
             */
78
0
            *digestInfoLen = it.len;
79
0
            *digestInfo = (unsigned char *)it.data;
80
0
            *digestAlgOut = givenDigestAlg;
81
0
            return SECSuccess;
82
0
        }
83
0
    }
84
85
0
    if (rv == SECSuccess) {
86
        /* The caller didn't specify a digest algorithm to use, so choose the
87
         * digest algorithm by parsing the AlgorithmIdentifier within the
88
         * DigestInfo.
89
         */
90
0
        di = SGN_DecodeDigestInfo(&it);
91
0
        if (!di) {
92
0
            rv = SECFailure;
93
0
        }
94
0
    }
95
96
0
    if (rv == SECSuccess) {
97
0
        *digestAlgOut = SECOID_GetAlgorithmTag(&di->digestAlgorithm);
98
0
        if (*digestAlgOut == SEC_OID_UNKNOWN) {
99
0
            rv = SECFailure;
100
0
        }
101
0
    }
102
103
0
    if (di) {
104
0
        SGN_DestroyDigestInfo(di);
105
0
    }
106
107
0
    if (rv == SECSuccess) {
108
0
        *digestInfoLen = it.len;
109
0
        *digestInfo = (unsigned char *)it.data;
110
0
    } else {
111
0
        if (it.data) {
112
0
            PORT_Free(it.data);
113
0
        }
114
0
        *digestInfo = NULL;
115
0
        *digestInfoLen = 0;
116
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
117
0
    }
118
119
0
    return rv;
120
0
}
121
122
struct VFYContextStr {
123
    SECOidTag hashAlg; /* the hash algorithm */
124
    SECKEYPublicKey *key;
125
    /*
126
     * This buffer holds either the digest or the full signature
127
     * depending on the type of the signature (key->keyType).  It is
128
     * defined as a union to make sure it always has enough space.
129
     *
130
     * Use the "buffer" union member to reference the buffer.
131
     * Note: do not take the size of the "buffer" union member.  Take
132
     * the size of the union or some other union member instead.
133
     */
134
    union {
135
        unsigned char buffer[1];
136
137
        /* the full DSA signature... 40 bytes */
138
        unsigned char dsasig[DSA_MAX_SIGNATURE_LEN];
139
        /* the full ECDSA signature */
140
        unsigned char ecdsasig[2 * MAX_ECKEY_LEN];
141
        /* the full RSA signature, only used in RSA-PSS */
142
        unsigned char rsasig[(RSA_MAX_MODULUS_BITS + 7) / 8];
143
        unsigned char gensig[MAX_SIGNATURE_LEN];
144
    } u;
145
    unsigned int signatureLen;
146
    unsigned int pkcs1RSADigestInfoLen;
147
    /* the encoded DigestInfo from a RSA PKCS#1 signature */
148
    unsigned char *pkcs1RSADigestInfo;
149
    void *wincx;
150
    void *hashcx;
151
    const SECHashObject *hashobj;
152
    PK11Context *vfycx;
153
    SECOidTag encAlg; /* enc alg */
154
    CK_MECHANISM_TYPE mech;
155
    PRBool hasSignature; /* true if the signature was provided in the
156
                          * VFY_CreateContext call.  If false, the
157
                          * signature must be provided with a
158
                          * VFY_EndWithSignature call. */
159
    SECItem mechparams;
160
};
161
162
static SECStatus
163
verifyPKCS1DigestInfo(const VFYContext *cx, const SECItem *digest)
164
0
{
165
0
    SECItem pkcs1DigestInfo;
166
0
    pkcs1DigestInfo.data = cx->pkcs1RSADigestInfo;
167
0
    pkcs1DigestInfo.len = cx->pkcs1RSADigestInfoLen;
168
0
    return _SGN_VerifyPKCS1DigestInfo(
169
0
        cx->hashAlg, digest, &pkcs1DigestInfo,
170
0
        PR_FALSE /*XXX: unsafeAllowMissingParameters*/);
171
0
}
172
173
static unsigned int
174
checkedSignatureLen(const SECKEYPublicKey *pubk)
175
0
{
176
0
    unsigned int sigLen = SECKEY_SignatureLen(pubk);
177
0
    if (sigLen == 0) {
178
        /* Error set by SECKEY_SignatureLen */
179
0
        return sigLen;
180
0
    }
181
0
    unsigned int maxSigLen;
182
0
    switch (pubk->keyType) {
183
0
        case rsaKey:
184
0
        case rsaPssKey:
185
0
            maxSigLen = (RSA_MAX_MODULUS_BITS + 7) / 8;
186
0
            break;
187
0
        case dsaKey:
188
0
            maxSigLen = DSA_MAX_SIGNATURE_LEN;
189
0
            break;
190
0
        case ecKey:
191
0
            maxSigLen = 2 * MAX_ECKEY_LEN;
192
0
            break;
193
0
        default:
194
0
            PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
195
0
            return 0;
196
0
    }
197
0
    PORT_Assert(maxSigLen <= MAX_SIGNATURE_LEN);
198
0
    if (sigLen > maxSigLen) {
199
0
        PORT_SetError(SEC_ERROR_INVALID_KEY);
200
0
        return 0;
201
0
    }
202
0
    return sigLen;
203
0
}
204
205
/*
206
 * decode the ECDSA or DSA signature from it's DER wrapping.
207
 * The unwrapped/raw signature is placed in the buffer pointed
208
 * to by dsig and has enough room for len bytes.
209
 */
210
static SECStatus
211
decodeECorDSASignature(SECOidTag algid, const SECItem *sig, unsigned char *dsig,
212
                       unsigned int len)
213
0
{
214
0
    SECItem *dsasig = NULL; /* also used for ECDSA */
215
216
    /* Safety: Ensure algId is as expected and that signature size is within maxmimums */
217
0
    if (algid == SEC_OID_ANSIX9_DSA_SIGNATURE) {
218
0
        if (len > DSA_MAX_SIGNATURE_LEN) {
219
0
            goto loser;
220
0
        }
221
0
    } else if (algid == SEC_OID_ANSIX962_EC_PUBLIC_KEY) {
222
0
        if (len > MAX_ECKEY_LEN * 2) {
223
0
            goto loser;
224
0
        }
225
0
    } else {
226
0
        goto loser;
227
0
    }
228
229
    /* Decode and pad to length */
230
0
    dsasig = DSAU_DecodeDerSigToLen((SECItem *)sig, len);
231
0
    if (dsasig == NULL) {
232
0
        goto loser;
233
0
    }
234
0
    if (dsasig->len != len) {
235
0
        SECITEM_FreeItem(dsasig, PR_TRUE);
236
0
        goto loser;
237
0
    }
238
239
0
    PORT_Memcpy(dsig, dsasig->data, len);
240
0
    SECITEM_FreeItem(dsasig, PR_TRUE);
241
242
0
    return SECSuccess;
243
244
0
loser:
245
0
    PORT_SetError(SEC_ERROR_BAD_DER);
246
0
    return SECFailure;
247
0
}
248
249
const SEC_ASN1Template hashParameterTemplate[] = {
250
    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECItem) },
251
    { SEC_ASN1_OBJECT_ID, 0 },
252
    { SEC_ASN1_SKIP_REST },
253
    { 0 }
254
};
255
256
/*
257
 * Get just the encryption algorithm from the signature algorithm
258
 */
259
SECOidTag
260
sec_GetEncAlgFromSigAlg(SECOidTag sigAlg)
261
0
{
262
    /* get the "encryption" algorithm */
263
0
    switch (sigAlg) {
264
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
265
0
        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
266
0
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
267
0
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
268
0
        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
269
0
        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
270
0
        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
271
0
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
272
0
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
273
0
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
274
0
            return SEC_OID_PKCS1_RSA_ENCRYPTION;
275
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
276
0
            return SEC_OID_PKCS1_RSA_PSS_SIGNATURE;
277
278
        /* what about normal DSA? */
279
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
280
0
        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
281
0
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
282
0
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
283
0
            return SEC_OID_ANSIX9_DSA_SIGNATURE;
284
0
        case SEC_OID_MISSI_DSS:
285
0
        case SEC_OID_MISSI_KEA_DSS:
286
0
        case SEC_OID_MISSI_KEA_DSS_OLD:
287
0
        case SEC_OID_MISSI_DSS_OLD:
288
0
            return SEC_OID_MISSI_DSS;
289
0
        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
290
0
        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
291
0
        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
292
0
        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
293
0
        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
294
0
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
295
0
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
296
0
            return SEC_OID_ANSIX962_EC_PUBLIC_KEY;
297
        /* we don't implement MD4 hashes */
298
0
        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
299
0
        default:
300
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
301
0
            break;
302
0
    }
303
0
    return SEC_OID_UNKNOWN;
304
0
}
305
static CK_MECHANISM_TYPE
306
sec_RSAPKCS1GetCombinedMech(SECOidTag hashalg)
307
0
{
308
0
    switch (hashalg) {
309
0
        case SEC_OID_MD5:
310
0
            return CKM_MD5_RSA_PKCS;
311
0
        case SEC_OID_MD2:
312
0
            return CKM_MD2_RSA_PKCS;
313
0
        case SEC_OID_SHA1:
314
0
            return CKM_SHA1_RSA_PKCS;
315
0
        case SEC_OID_SHA224:
316
0
            return CKM_SHA224_RSA_PKCS;
317
0
        case SEC_OID_SHA256:
318
0
            return CKM_SHA256_RSA_PKCS;
319
0
        case SEC_OID_SHA384:
320
0
            return CKM_SHA384_RSA_PKCS;
321
0
        case SEC_OID_SHA512:
322
0
            return CKM_SHA512_RSA_PKCS;
323
0
        default:
324
0
            break;
325
0
    }
326
0
    return CKM_INVALID_MECHANISM;
327
0
}
328
329
static CK_MECHANISM_TYPE
330
sec_RSAPSSGetCombinedMech(SECOidTag hashalg)
331
0
{
332
0
    switch (hashalg) {
333
0
        case SEC_OID_SHA1:
334
0
            return CKM_SHA1_RSA_PKCS_PSS;
335
0
        case SEC_OID_SHA224:
336
0
            return CKM_SHA224_RSA_PKCS_PSS;
337
0
        case SEC_OID_SHA256:
338
0
            return CKM_SHA256_RSA_PKCS_PSS;
339
0
        case SEC_OID_SHA384:
340
0
            return CKM_SHA384_RSA_PKCS_PSS;
341
0
        case SEC_OID_SHA512:
342
0
            return CKM_SHA512_RSA_PKCS_PSS;
343
0
        default:
344
0
            break;
345
0
    }
346
0
    return CKM_INVALID_MECHANISM;
347
0
}
348
349
static CK_MECHANISM_TYPE
350
sec_DSAGetCombinedMech(SECOidTag hashalg)
351
0
{
352
0
    switch (hashalg) {
353
0
        case SEC_OID_SHA1:
354
0
            return CKM_DSA_SHA1;
355
0
        case SEC_OID_SHA224:
356
0
            return CKM_DSA_SHA224;
357
0
        case SEC_OID_SHA256:
358
0
            return CKM_DSA_SHA256;
359
0
        case SEC_OID_SHA384:
360
0
            return CKM_DSA_SHA384;
361
0
        case SEC_OID_SHA512:
362
0
            return CKM_DSA_SHA512;
363
0
        default:
364
0
            break;
365
0
    }
366
0
    return CKM_INVALID_MECHANISM;
367
0
}
368
static CK_MECHANISM_TYPE
369
sec_ECDSAGetCombinedMech(SECOidTag hashalg)
370
0
{
371
0
    switch (hashalg) {
372
0
        case SEC_OID_SHA1:
373
0
            return CKM_ECDSA_SHA1;
374
0
        case SEC_OID_SHA224:
375
0
            return CKM_ECDSA_SHA224;
376
0
        case SEC_OID_SHA256:
377
0
            return CKM_ECDSA_SHA256;
378
0
        case SEC_OID_SHA384:
379
0
            return CKM_ECDSA_SHA384;
380
0
        case SEC_OID_SHA512:
381
0
            return CKM_ECDSA_SHA512;
382
0
        default:
383
0
            break;
384
0
    }
385
0
    return CKM_INVALID_MECHANISM;
386
0
}
387
388
static CK_MECHANISM_TYPE
389
sec_GetCombinedMech(SECOidTag encalg, SECOidTag hashalg)
390
0
{
391
0
    switch (encalg) {
392
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
393
0
            return sec_RSAPKCS1GetCombinedMech(hashalg);
394
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
395
0
            return sec_RSAPSSGetCombinedMech(hashalg);
396
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
397
0
            return sec_ECDSAGetCombinedMech(hashalg);
398
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
399
0
            return sec_DSAGetCombinedMech(hashalg);
400
0
        default:
401
0
            break;
402
0
    }
403
0
    return CKM_INVALID_MECHANISM;
404
0
}
405
406
/*
407
 * Pulls the hash algorithm, signing algorithm, and key type out of a
408
 * composite algorithm.
409
 *
410
 * key: pointer to the public key. Should be NULL if called for a sign operation.
411
 * sigAlg: the composite algorithm to dissect.
412
 * hashalg: address of a SECOidTag which will be set with the hash algorithm.
413
 * encalg: address of a SECOidTag which will be set with the signing alg.
414
 * mechp: address of a PCKS #11 Mechanism which will be set to the
415
 *  combined hash/encrypt mechanism. If set to CKM_INVALID_MECHANISM, the code
416
 *  will fall back to external hashing.
417
 * mechparams: address of a SECItem will set to the parameters for the combined
418
 *  hash/encrypt mechanism.
419
 *
420
 * Returns: SECSuccess if the algorithm was acceptable, SECFailure if the
421
 *  algorithm was not found or was not a signing algorithm.
422
 */
423
SECStatus
424
sec_DecodeSigAlg(const SECKEYPublicKey *key, SECOidTag sigAlg,
425
                 const SECItem *param, SECOidTag *encalgp, SECOidTag *hashalg,
426
                 CK_MECHANISM_TYPE *mechp, SECItem *mechparamsp)
427
0
{
428
0
    unsigned int len;
429
0
    PLArenaPool *arena;
430
0
    SECStatus rv;
431
0
    SECItem oid;
432
0
    SECOidTag encalg;
433
0
    char *evp;
434
435
0
    PR_ASSERT(hashalg != NULL);
436
0
    PR_ASSERT(encalgp != NULL);
437
0
    PR_ASSERT(mechp != NULL);
438
    /* Get the expected combined mechanism from the signature OID
439
     * We'll override it in the table below if necessary */
440
0
    *mechp = PK11_AlgtagToMechanism(sigAlg);
441
0
    if (mechparamsp) {
442
0
        mechparamsp->data = NULL;
443
0
        mechparamsp->len = 0;
444
0
    }
445
446
0
    switch (sigAlg) {
447
        /* We probably shouldn't be generating MD2 signatures either */
448
0
        case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
449
0
            *hashalg = SEC_OID_MD2;
450
0
            break;
451
0
        case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
452
0
            *hashalg = SEC_OID_MD5;
453
0
            break;
454
0
        case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION:
455
0
        case SEC_OID_ISO_SHA_WITH_RSA_SIGNATURE:
456
0
        case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE:
457
0
            *hashalg = SEC_OID_SHA1;
458
0
            break;
459
0
        case SEC_OID_PKCS1_RSA_ENCRYPTION:
460
            /* SEC_OID_PKCS1_RSA_ENCRYPTION returns the generic
461
             * CKM_RSA_PKCS mechanism, which isn't a combined mechanism.
462
             * We don't have a hash, so we need to fall back to the old
463
             * code which gets the hashalg by decoding the signature */
464
0
            *mechp = CKM_INVALID_MECHANISM;
465
0
            *hashalg = SEC_OID_UNKNOWN; /* get it from the RSA signature */
466
0
            break;
467
0
        case SEC_OID_PKCS1_RSA_PSS_SIGNATURE:
468
            /* SEC_OID_PKCS1_RSA_PSS_SIGNATURE returns the generic
469
             * CKM_RSA_PSS_PKCS mechanism, which isn't a combined mechanism.
470
             * If successful, we'll select the mechanism below, set it to
471
             * invalid here incase we aren't successful */
472
0
            *mechp = CKM_INVALID_MECHANISM;
473
0
            CK_RSA_PKCS_PSS_PARAMS *rsapssmechparams = NULL;
474
0
            CK_RSA_PKCS_PSS_PARAMS space;
475
476
            /* if we don't have a mechanism parameter to put the data in
477
             * we don't need to return it, just use a stack buffer */
478
0
            if (mechparamsp == NULL) {
479
0
                rsapssmechparams = &space;
480
0
            } else {
481
0
                rsapssmechparams = PORT_ZNew(CK_RSA_PKCS_PSS_PARAMS);
482
0
            }
483
0
            if (rsapssmechparams == NULL) {
484
0
                return SECFailure;
485
0
            }
486
0
            if (param && param->data) {
487
0
                PORTCheapArenaPool tmpArena;
488
489
0
                PORT_InitCheapArena(&tmpArena, DER_DEFAULT_CHUNKSIZE);
490
0
                rv = sec_DecodeRSAPSSParamsToMechanism(&tmpArena.arena, param,
491
0
                                                       rsapssmechparams, hashalg);
492
0
                PORT_DestroyCheapArena(&tmpArena);
493
494
                /* only accept hash algorithms */
495
0
                if (rv != SECSuccess || HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
496
                    /* error set by sec_DecodeRSAPSSParams or HASH_GetHashTypeByOidTag */
497
0
                    if (mechparamsp)
498
0
                        PORT_Free(rsapssmechparams);
499
0
                    return SECFailure;
500
0
                }
501
0
            } else {
502
0
                *hashalg = SEC_OID_SHA1; /* default, SHA-1 */
503
0
                rsapssmechparams->hashAlg = CKM_SHA_1;
504
0
                rsapssmechparams->mgf = CKG_MGF1_SHA1;
505
0
                rsapssmechparams->sLen = SHA1_LENGTH;
506
0
            }
507
0
            *mechp = sec_RSAPSSGetCombinedMech(*hashalg);
508
0
            if (mechparamsp) {
509
0
                mechparamsp->data = (unsigned char *)rsapssmechparams;
510
0
                mechparamsp->len = sizeof(*rsapssmechparams);
511
0
            }
512
0
            break;
513
514
0
        case SEC_OID_ANSIX962_ECDSA_SHA224_SIGNATURE:
515
0
        case SEC_OID_PKCS1_SHA224_WITH_RSA_ENCRYPTION:
516
0
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA224_DIGEST:
517
0
            *hashalg = SEC_OID_SHA224;
518
0
            break;
519
0
        case SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE:
520
0
        case SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION:
521
0
        case SEC_OID_NIST_DSA_SIGNATURE_WITH_SHA256_DIGEST:
522
0
            *hashalg = SEC_OID_SHA256;
523
0
            break;
524
0
        case SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE:
525
0
        case SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION:
526
0
            *hashalg = SEC_OID_SHA384;
527
0
            break;
528
0
        case SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE:
529
0
        case SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION:
530
0
            *hashalg = SEC_OID_SHA512;
531
0
            break;
532
533
        /* what about normal DSA? */
534
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST:
535
0
        case SEC_OID_BOGUS_DSA_SIGNATURE_WITH_SHA1_DIGEST:
536
0
        case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE:
537
0
            *hashalg = SEC_OID_SHA1;
538
0
            break;
539
0
        case SEC_OID_MISSI_DSS:
540
0
        case SEC_OID_MISSI_KEA_DSS:
541
0
        case SEC_OID_MISSI_KEA_DSS_OLD:
542
0
        case SEC_OID_MISSI_DSS_OLD:
543
0
            *mechp = CKM_DSA_SHA1;
544
0
            *hashalg = SEC_OID_SHA1;
545
0
            break;
546
0
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_RECOMMENDED_DIGEST:
547
            /* This is an EC algorithm. Recommended means the largest
548
             * hash algorithm that is not reduced by the keysize of
549
             * the EC algorithm. Note that key strength is in bytes and
550
             * algorithms are specified in bits. Never use an algorithm
551
             * weaker than sha1. */
552
0
            len = SECKEY_PublicKeyStrength(key);
553
0
            if (len < 28) { /* 28 bytes == 224 bits */
554
0
                *hashalg = SEC_OID_SHA1;
555
0
            } else if (len < 32) { /* 32 bytes == 256 bits */
556
0
                *hashalg = SEC_OID_SHA224;
557
0
            } else if (len < 48) { /* 48 bytes == 384 bits */
558
0
                *hashalg = SEC_OID_SHA256;
559
0
            } else if (len < 64) { /* 48 bytes == 512 bits */
560
0
                *hashalg = SEC_OID_SHA384;
561
0
            } else {
562
                /* use the largest in this case */
563
0
                *hashalg = SEC_OID_SHA512;
564
0
            }
565
0
            *mechp = sec_ECDSAGetCombinedMech(*hashalg);
566
0
            break;
567
0
        case SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST:
568
0
            if (param == NULL) {
569
0
                PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
570
0
                return SECFailure;
571
0
            }
572
0
            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
573
0
            if (arena == NULL) {
574
0
                return SECFailure;
575
0
            }
576
0
            rv = SEC_QuickDERDecodeItem(arena, &oid, hashParameterTemplate, param);
577
0
            if (rv == SECSuccess) {
578
0
                *hashalg = SECOID_FindOIDTag(&oid);
579
0
            }
580
0
            PORT_FreeArena(arena, PR_FALSE);
581
0
            if (rv != SECSuccess) {
582
0
                return rv;
583
0
            }
584
            /* only accept hash algorithms */
585
0
            if (HASH_GetHashTypeByOidTag(*hashalg) == HASH_AlgNULL) {
586
                /* error set by HASH_GetHashTypeByOidTag */
587
0
                return SECFailure;
588
0
            }
589
0
            *mechp = sec_ECDSAGetCombinedMech(*hashalg);
590
0
            break;
591
        /* we don't implement MD4 hashes */
592
0
        case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
593
0
        default:
594
0
            *mechp = CKM_INVALID_MECHANISM;
595
0
            PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
596
0
            return SECFailure;
597
0
    }
598
599
0
    encalg = sec_GetEncAlgFromSigAlg(sigAlg);
600
0
    if (encalg == SEC_OID_UNKNOWN) {
601
0
        *mechp = CKM_INVALID_MECHANISM;
602
0
        SECITEM_FreeItem(mechparamsp, PR_FALSE);
603
0
        return SECFailure;
604
0
    }
605
0
    *encalgp = encalg;
606
    /* for testing, we want to be able to turn off combo signatures to
607
     * 1) make sure the fallback code is working correctly so we know
608
     * we can handle cases where the fallback doesn't work.
609
     * 2) make sure that the combo code is compatible with the non-combo
610
     * versions.
611
     * We know if we are signing or verifying based on the value of 'key'.
612
     * Since key is a public key, then it's set to NULL for signing */
613
0
    evp = PR_GetEnvSecure("NSS_COMBO_SIGNATURES");
614
0
    if (evp) {
615
0
        if (PORT_Strcasecmp(evp, "none") == 0) {
616
0
            *mechp = CKM_INVALID_MECHANISM;
617
0
        } else if (key && (PORT_Strcasecmp(evp, "signonly") == 0)) {
618
0
            *mechp = CKM_INVALID_MECHANISM;
619
0
        } else if (!key && (PORT_Strcasecmp(evp, "vfyonly") == 0)) {
620
0
            *mechp = CKM_INVALID_MECHANISM;
621
0
        }
622
        /* anything else we take as use combo, which is the default */
623
0
    }
624
625
0
    return SECSuccess;
626
0
}
627
628
SECStatus
629
vfy_ImportPublicKey(VFYContext *cx)
630
0
{
631
0
    PK11SlotInfo *slot;
632
0
    CK_OBJECT_HANDLE objID;
633
634
0
    if (cx->key->pkcs11Slot &&
635
0
        PK11_DoesMechanismFlag(cx->key->pkcs11Slot,
636
0
                               cx->mech, CKF_VERIFY)) {
637
0
        return SECSuccess;
638
0
    }
639
0
    slot = PK11_GetBestSlotWithAttributes(cx->mech, CKF_VERIFY, 0, cx->wincx);
640
0
    if (slot == NULL) {
641
0
        return SECFailure; /* can't find a slot, fall back to
642
                            * normal processing */
643
0
    }
644
0
    objID = PK11_ImportPublicKey(slot, cx->key, PR_FALSE);
645
0
    PK11_FreeSlot(slot);
646
0
    return objID == CK_INVALID_HANDLE ? SECFailure : SECSuccess;
647
0
}
648
649
/* Sometimes there are differences between how DER encodes a
650
 * signature and how it's encoded in PKCS #11. This function converts the
651
 * DER form to the PKCS #11 form. it also verify signature length based
652
 * on the key, and verifies that length will fit in our buffer. */
653
static SECStatus
654
vfy_SetPKCS11SigFromX509Sig(VFYContext *cx, const SECItem *sig)
655
0
{
656
0
    unsigned int sigLen;
657
658
    /* skip the legacy RSA PKCS #11 case, it's always handled separately */
659
0
    if ((cx->key->keyType == rsaKey) && (cx->mech == CKM_INVALID_MECHANISM) &&
660
0
        (cx->encAlg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE)) {
661
0
        return SECSuccess;
662
0
    }
663
664
0
    sigLen = checkedSignatureLen(cx->key);
665
    /* Check signature length is within limits */
666
0
    if (sigLen == 0) {
667
        /* error set by checkedSignatureLen */
668
0
        return SECFailure;
669
0
    }
670
0
    if (sigLen > sizeof(cx->u)) {
671
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
672
0
        return SECFailure;
673
0
    }
674
    /* save the authenticated length */
675
0
    cx->signatureLen = sigLen;
676
0
    switch (cx->encAlg) {
677
0
        case SEC_OID_ANSIX9_DSA_SIGNATURE:
678
0
        case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
679
            /* decodeECorDSASignature will check sigLen == sig->len after padding */
680
0
            return decodeECorDSASignature(cx->encAlg, sig, cx->u.buffer, sigLen);
681
0
        default:
682
0
            break;
683
0
    }
684
    /* all other cases, no transform needed, just copy the signature */
685
0
    if (sig->len != sigLen) {
686
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
687
0
        return SECFailure;
688
0
    }
689
0
    PORT_Memcpy(cx->u.buffer, sig->data, sigLen);
690
0
    return SECSuccess;
691
0
}
692
693
/*
694
 * we can verify signatures that come from 2 different sources:
695
 *  one in with the signature contains a signature oid, and the other
696
 *  in which the signature is managed by a Public key (encAlg) oid
697
 *  and a hash oid. The latter is the more basic, so that's what
698
 *  our base vfyCreate function takes.
699
 *
700
 * Modern signature algorithms builds the hashing into the algorithm, and
701
 *  some tokens (like smart cards), purposefully only export hash & sign
702
 *  combo mechanisms (which gives stronger guarrentees on key type usage
703
 *  for RSA operations). If mech is set to a PKCS #11 mechanism, we assume
704
 *  we can do the combined operations, otherwise we fall back to manually
705
 *  hashing then signing.
706
 *
707
 * This function adopts the mechparamsp parameter, so if we fail before
708
 *  setting up the context, we need to free any space associated with it
709
 *  before we return.
710
 *
711
 * There is one noteworthy corner case, if we are using an RSA key, and the
712
 * signature block is provided, then the hashAlg can be specified as
713
 * SEC_OID_UNKNOWN. In this case, verify will use the hash oid supplied
714
 * in the RSA signature block.
715
 */
716
static VFYContext *
717
vfy_CreateContext(const SECKEYPublicKey *key, const SECItem *sig,
718
                  SECOidTag encAlg, SECOidTag hashAlg, CK_MECHANISM_TYPE mech,
719
                  SECItem *mechparamsp, SECOidTag *hash, PRBool prehash,
720
                  void *wincx)
721
0
{
722
0
    VFYContext *cx;
723
0
    SECStatus rv;
724
0
    KeyType type;
725
0
    PRUint32 policyFlags;
726
0
    PRInt32 optFlags;
727
728
    /* make sure the encryption algorithm matches the key type */
729
    /* RSA-PSS algorithm can be used with both rsaKey and rsaPssKey */
730
0
    type = seckey_GetKeyType(encAlg);
731
0
    if ((key->keyType != type) &&
732
0
        ((key->keyType != rsaKey) || (type != rsaPssKey))) {
733
0
        SECITEM_FreeItem(mechparamsp, PR_FALSE);
734
0
        PORT_SetError(SEC_ERROR_PKCS7_KEYALG_MISMATCH);
735
0
        return NULL;
736
0
    }
737
0
    if (NSS_OptionGet(NSS_KEY_SIZE_POLICY_FLAGS, &optFlags) != SECFailure) {
738
0
        if (optFlags & NSS_KEY_SIZE_POLICY_VERIFY_FLAG) {
739
0
            rv = SECKEY_EnforceKeySize(key->keyType,
740
0
                                       SECKEY_PublicKeyStrengthInBits(key),
741
0
                                       SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
742
0
            if (rv != SECSuccess) {
743
0
                SECITEM_FreeItem(mechparamsp, PR_FALSE);
744
0
                return NULL;
745
0
            }
746
0
        }
747
0
    }
748
    /* check the policy on the encryption algorithm */
749
0
    if ((NSS_GetAlgorithmPolicy(encAlg, &policyFlags) == SECFailure) ||
750
0
        !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
751
0
        SECITEM_FreeItem(mechparamsp, PR_FALSE);
752
0
        PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
753
0
        return NULL;
754
0
    }
755
756
0
    cx = (VFYContext *)PORT_ZAlloc(sizeof(VFYContext));
757
0
    if (cx == NULL) {
758
        /* after this point mechparamsp is 'owned' by the context and will be
759
         * freed by Destroy context for any other failures here */
760
0
        SECITEM_FreeItem(mechparamsp, PR_FALSE);
761
0
        goto loser;
762
0
    }
763
764
0
    cx->wincx = wincx;
765
0
    cx->hasSignature = (sig != NULL);
766
0
    cx->encAlg = encAlg;
767
0
    cx->hashAlg = hashAlg;
768
0
    cx->mech = mech;
769
0
    if (mechparamsp) {
770
0
        cx->mechparams = *mechparamsp;
771
0
    } else {
772
        /* probably needs to have a call to set the default
773
         * paramseters based on hashAlg and encAlg */
774
0
        cx->mechparams.data = NULL;
775
0
        cx->mechparams.len = 0;
776
0
    }
777
0
    cx->key = SECKEY_CopyPublicKey(key);
778
0
    cx->pkcs1RSADigestInfo = NULL;
779
0
    if (mech != CKM_INVALID_MECHANISM) {
780
0
        rv = vfy_ImportPublicKey(cx);
781
        /* if we can't import the key, then we probably can't
782
         * support the requested combined mechanism, fallback
783
         * to the non-combined method */
784
0
        if (rv != SECSuccess) {
785
0
            cx->mech = mech = CKM_INVALID_MECHANISM;
786
0
        }
787
0
    }
788
0
    if (sig) {
789
        /* sigh, if we are prehashing, we still need to do verifyRecover
790
         * recover for RSA PKCS #1 */
791
0
        if ((mech == CKM_INVALID_MECHANISM || prehash) && (type == rsaKey)) {
792
            /* in traditional rsa PKCS #1, we use verify recover to get
793
             * the encoded RSADigestInfo. In all other cases we just
794
             * stash the signature encoded in PKCS#11 in our context */
795
0
            rv = recoverPKCS1DigestInfo(hashAlg, &cx->hashAlg,
796
0
                                        &cx->pkcs1RSADigestInfo,
797
0
                                        &cx->pkcs1RSADigestInfoLen,
798
0
                                        cx->key,
799
0
                                        sig, wincx);
800
0
        } else {
801
            /* at this point hashAlg should be known. Only the RSA case
802
             * enters here with hashAlg unknown, and it's found out
803
             * above */
804
0
            PORT_Assert(hashAlg != SEC_OID_UNKNOWN);
805
0
            rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
806
0
        }
807
0
        if (rv != SECSuccess) {
808
0
            goto loser;
809
0
        }
810
0
    }
811
812
    /* check hash alg again, RSA may have changed it.*/
813
0
    if (HASH_GetHashTypeByOidTag(cx->hashAlg) == HASH_AlgNULL) {
814
        /* error set by HASH_GetHashTypeByOidTag */
815
0
        goto loser;
816
0
    }
817
    /* check the policy on the hash algorithm. Do this after
818
     * the rsa decode because some uses of this function get hash implicitly
819
     * from the RSA signature itself. */
820
0
    if ((NSS_GetAlgorithmPolicy(cx->hashAlg, &policyFlags) == SECFailure) ||
821
0
        !(policyFlags & NSS_USE_ALG_IN_ANY_SIGNATURE)) {
822
0
        PORT_SetError(SEC_ERROR_SIGNATURE_ALGORITHM_DISABLED);
823
0
        goto loser;
824
0
    }
825
826
0
    if (hash) {
827
0
        *hash = cx->hashAlg;
828
0
    }
829
0
    return cx;
830
831
0
loser:
832
0
    if (cx) {
833
0
        VFY_DestroyContext(cx, PR_TRUE);
834
0
    }
835
0
    return 0;
836
0
}
837
838
VFYContext *
839
VFY_CreateContext(SECKEYPublicKey *key, SECItem *sig, SECOidTag sigAlg,
840
                  void *wincx)
841
0
{
842
0
    SECOidTag encAlg, hashAlg;
843
0
    CK_MECHANISM_TYPE mech;
844
0
    SECItem mechparams;
845
0
    SECStatus rv = sec_DecodeSigAlg(key, sigAlg, NULL, &encAlg, &hashAlg,
846
0
                                    &mech, &mechparams);
847
0
    if (rv != SECSuccess) {
848
0
        return NULL;
849
0
    }
850
0
    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech,
851
0
                             &mechparams, NULL, PR_FALSE, wincx);
852
0
}
853
854
VFYContext *
855
VFY_CreateContextDirect(const SECKEYPublicKey *key, const SECItem *sig,
856
                        SECOidTag encAlg, SECOidTag hashAlg,
857
                        SECOidTag *hash, void *wincx)
858
0
{
859
0
    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
860
0
    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, NULL,
861
0
                             hash, PR_FALSE, wincx);
862
0
}
863
864
VFYContext *
865
VFY_CreateContextWithAlgorithmID(const SECKEYPublicKey *key, const SECItem *sig,
866
                                 const SECAlgorithmID *sigAlgorithm, SECOidTag *hash, void *wincx)
867
0
{
868
0
    SECOidTag encAlg, hashAlg;
869
0
    CK_MECHANISM_TYPE mech;
870
0
    SECItem mechparams;
871
0
    SECStatus rv = sec_DecodeSigAlg(key,
872
0
                                    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
873
0
                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
874
0
                                    &mech, &mechparams);
875
0
    if (rv != SECSuccess) {
876
0
        return NULL;
877
0
    }
878
879
0
    return vfy_CreateContext(key, sig, encAlg, hashAlg, mech, &mechparams,
880
0
                             hash, PR_FALSE, wincx);
881
0
}
882
883
void
884
VFY_DestroyContext(VFYContext *cx, PRBool freeit)
885
0
{
886
0
    if (cx) {
887
0
        if (cx->hashcx != NULL) {
888
0
            (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
889
0
            cx->hashcx = NULL;
890
0
        }
891
0
        if (cx->vfycx != NULL) {
892
0
            (void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
893
0
            cx->vfycx = NULL;
894
0
        }
895
0
        if (cx->key) {
896
0
            SECKEY_DestroyPublicKey(cx->key);
897
0
        }
898
0
        if (cx->pkcs1RSADigestInfo) {
899
0
            PORT_Free(cx->pkcs1RSADigestInfo);
900
0
        }
901
0
        SECITEM_FreeItem(&cx->mechparams, PR_FALSE);
902
0
        if (freeit) {
903
0
            PORT_ZFree(cx, sizeof(VFYContext));
904
0
        }
905
0
    }
906
0
}
907
908
SECStatus
909
VFY_Begin(VFYContext *cx)
910
0
{
911
0
    if (cx->hashcx != NULL) {
912
0
        (*cx->hashobj->destroy)(cx->hashcx, PR_TRUE);
913
0
        cx->hashcx = NULL;
914
0
    }
915
0
    if (cx->vfycx != NULL) {
916
0
        (void)PK11_DestroyContext(cx->vfycx, PR_TRUE);
917
0
        cx->vfycx = NULL;
918
0
    }
919
0
    if (cx->mech != CKM_INVALID_MECHANISM) {
920
0
        cx->vfycx = PK11_CreateContextByPubKey(cx->mech, CKA_VERIFY, cx->key,
921
0
                                               &cx->mechparams, cx->wincx);
922
0
        if (!cx->vfycx)
923
0
            return SECFailure;
924
0
        return SECSuccess;
925
0
    }
926
0
    cx->hashobj = HASH_GetHashObjectByOidTag(cx->hashAlg);
927
0
    if (!cx->hashobj)
928
0
        return SECFailure; /* error code is set */
929
930
0
    cx->hashcx = (*cx->hashobj->create)();
931
0
    if (cx->hashcx == NULL)
932
0
        return SECFailure;
933
934
0
    (*cx->hashobj->begin)(cx->hashcx);
935
0
    return SECSuccess;
936
0
}
937
938
SECStatus
939
VFY_Update(VFYContext *cx, const unsigned char *input, unsigned inputLen)
940
0
{
941
0
    if (cx->hashcx == NULL) {
942
0
        if (cx->vfycx == NULL) {
943
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
944
0
            return SECFailure;
945
0
        }
946
0
        return PK11_DigestOp(cx->vfycx, input, inputLen);
947
0
    }
948
0
    (*cx->hashobj->update)(cx->hashcx, input, inputLen);
949
0
    return SECSuccess;
950
0
}
951
952
static SECStatus
953
vfy_SingleShot(VFYContext *cx, const unsigned char *buf, int len)
954
0
{
955
0
    SECStatus rv;
956
    /* if we have the combo mechanism, do a direct verify */
957
0
    if (cx->mech != CKM_INVALID_MECHANISM) {
958
0
        SECItem sig = { siBuffer, cx->u.gensig, cx->signatureLen };
959
0
        SECItem data = { siBuffer, (unsigned char *)buf, len };
960
0
        return PK11_VerifyWithMechanism(cx->key, cx->mech, &cx->mechparams,
961
0
                                        &sig, &data, cx->wincx);
962
0
    }
963
0
    rv = VFY_Begin(cx);
964
0
    if (rv != SECSuccess) {
965
0
        return rv;
966
0
    }
967
0
    rv = VFY_Update(cx, (unsigned char *)buf, len);
968
0
    if (rv != SECSuccess) {
969
0
        return rv;
970
0
    }
971
0
    return VFY_End(cx);
972
0
}
973
974
SECStatus
975
VFY_EndWithSignature(VFYContext *cx, SECItem *sig)
976
0
{
977
0
    unsigned char final[HASH_LENGTH_MAX];
978
0
    unsigned part;
979
0
    SECStatus rv;
980
981
    /* make sure our signature is set (either previously nor now) */
982
0
    if (sig) {
983
0
        rv = vfy_SetPKCS11SigFromX509Sig(cx, sig);
984
0
        if (rv != SECSuccess) {
985
0
            return SECFailure;
986
0
        }
987
0
    } else if (cx->hasSignature == PR_FALSE) {
988
0
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
989
0
        return SECFailure;
990
0
    }
991
992
0
    if (cx->hashcx == NULL) {
993
0
        unsigned int dummy;
994
0
        if (cx->vfycx == NULL) {
995
0
            PORT_SetError(SEC_ERROR_INVALID_ARGS);
996
0
            return SECFailure;
997
0
        }
998
0
        return PK11_DigestFinal(cx->vfycx, cx->u.gensig, &dummy,
999
0
                                cx->signatureLen);
1000
0
    }
1001
0
    (*cx->hashobj->end)(cx->hashcx, final, &part, sizeof(final));
1002
0
    SECItem gensig = { siBuffer, cx->u.gensig, cx->signatureLen };
1003
0
    SECItem hash = { siBuffer, final, part };
1004
0
    PORT_Assert(part <= sizeof(final));
1005
    /* handle the algorithm specific final call */
1006
0
    switch (cx->key->keyType) {
1007
0
        case ecKey:
1008
0
        case dsaKey:
1009
0
            if (PK11_Verify(cx->key, &gensig, &hash, cx->wincx) != SECSuccess) {
1010
0
                PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1011
0
                return SECFailure;
1012
0
            }
1013
0
            break;
1014
0
        case rsaKey:
1015
0
            if (cx->encAlg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
1016
0
                if (PK11_VerifyWithMechanism(cx->key, CKM_RSA_PKCS_PSS,
1017
0
                                             &cx->mechparams, &gensig, &hash,
1018
0
                                             cx->wincx) != SECSuccess) {
1019
0
                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1020
0
                    return SECFailure;
1021
0
                }
1022
0
            } else {
1023
0
                if (sig) {
1024
0
                    SECOidTag hashid;
1025
0
                    PORT_Assert(cx->hashAlg != SEC_OID_UNKNOWN);
1026
0
                    rv = recoverPKCS1DigestInfo(cx->hashAlg, &hashid,
1027
0
                                                &cx->pkcs1RSADigestInfo,
1028
0
                                                &cx->pkcs1RSADigestInfoLen,
1029
0
                                                cx->key,
1030
0
                                                sig, cx->wincx);
1031
0
                    if (rv != SECSuccess) {
1032
0
                        return SECFailure;
1033
0
                    }
1034
0
                    PORT_Assert(cx->hashAlg == hashid);
1035
0
                }
1036
0
                return verifyPKCS1DigestInfo(cx, &hash);
1037
0
            }
1038
0
            break;
1039
0
        default:
1040
0
            PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1041
0
            return SECFailure; /* shouldn't happen */
1042
0
    }
1043
0
    return SECSuccess;
1044
0
}
1045
1046
SECStatus
1047
VFY_End(VFYContext *cx)
1048
0
{
1049
0
    return VFY_EndWithSignature(cx, NULL);
1050
0
}
1051
1052
/************************************************************************/
1053
/*
1054
 * Verify that a previously-computed digest matches a signature.
1055
 */
1056
static SECStatus
1057
vfy_VerifyDigest(const SECItem *digest, const SECKEYPublicKey *key,
1058
                 const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
1059
                 CK_MECHANISM_TYPE mech, SECItem *mechparamsp, void *wincx)
1060
0
{
1061
0
    SECStatus rv;
1062
0
    VFYContext *cx;
1063
0
    SECItem dsasig; /* also used for ECDSA */
1064
0
    rv = SECFailure;
1065
1066
0
    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
1067
0
                           NULL, PR_TRUE, wincx);
1068
0
    if (cx != NULL) {
1069
0
        switch (key->keyType) {
1070
0
            case rsaKey:
1071
                /* PSS isn't handled here for VerifyDigest. SSL
1072
                 * calls PK11_Verify directly */
1073
0
                rv = verifyPKCS1DigestInfo(cx, digest);
1074
                /* Error (if any) set by verifyPKCS1DigestInfo */
1075
0
                break;
1076
0
            case ecKey:
1077
0
            case dsaKey:
1078
0
                dsasig.data = cx->u.buffer;
1079
0
                dsasig.len = checkedSignatureLen(cx->key);
1080
0
                if (dsasig.len == 0) {
1081
                    /* Error set by checkedSignatureLen */
1082
0
                    rv = SECFailure;
1083
0
                    break;
1084
0
                }
1085
0
                if (dsasig.len > sizeof(cx->u)) {
1086
0
                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1087
0
                    rv = SECFailure;
1088
0
                    break;
1089
0
                }
1090
0
                rv = PK11_Verify(cx->key, &dsasig, (SECItem *)digest, cx->wincx);
1091
0
                if (rv != SECSuccess) {
1092
0
                    PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1093
0
                }
1094
0
                break;
1095
0
            default:
1096
0
                break;
1097
0
        }
1098
0
        VFY_DestroyContext(cx, PR_TRUE);
1099
0
    }
1100
0
    return rv;
1101
0
}
1102
1103
SECStatus
1104
VFY_VerifyDigestDirect(const SECItem *digest, const SECKEYPublicKey *key,
1105
                       const SECItem *sig, SECOidTag encAlg,
1106
                       SECOidTag hashAlg, void *wincx)
1107
0
{
1108
0
    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
1109
0
    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg, mech,
1110
0
                            NULL, wincx);
1111
0
}
1112
1113
SECStatus
1114
VFY_VerifyDigest(SECItem *digest, SECKEYPublicKey *key, SECItem *sig,
1115
                 SECOidTag algid, void *wincx)
1116
0
{
1117
0
    SECOidTag encAlg, hashAlg;
1118
0
    CK_MECHANISM_TYPE mech;
1119
0
    SECItem mechparams;
1120
0
    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
1121
0
                                    &mech, &mechparams);
1122
0
    if (rv != SECSuccess) {
1123
0
        return SECFailure;
1124
0
    }
1125
0
    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
1126
0
                            mech, &mechparams, wincx);
1127
0
}
1128
1129
/*
1130
 * this function takes an optional hash oid, which the digest function
1131
 * will be compared with our target hash value.
1132
 */
1133
SECStatus
1134
VFY_VerifyDigestWithAlgorithmID(const SECItem *digest,
1135
                                const SECKEYPublicKey *key, const SECItem *sig,
1136
                                const SECAlgorithmID *sigAlgorithm,
1137
                                SECOidTag hashCmp, void *wincx)
1138
0
{
1139
0
    SECOidTag encAlg, hashAlg;
1140
0
    CK_MECHANISM_TYPE mech;
1141
0
    SECItem mechparams;
1142
0
    SECStatus rv = sec_DecodeSigAlg(key,
1143
0
                                    SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm),
1144
0
                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
1145
0
                                    &mech, &mechparams);
1146
0
    if (rv != SECSuccess) {
1147
0
        return rv;
1148
0
    }
1149
0
    if (hashCmp != SEC_OID_UNKNOWN &&
1150
0
        hashAlg != SEC_OID_UNKNOWN &&
1151
0
        hashCmp != hashAlg) {
1152
0
        if (mechparams.data != NULL) {
1153
0
            PORT_Free(mechparams.data);
1154
0
        }
1155
0
        PORT_SetError(SEC_ERROR_BAD_SIGNATURE);
1156
0
        return SECFailure;
1157
0
    }
1158
0
    return vfy_VerifyDigest(digest, key, sig, encAlg, hashAlg,
1159
0
                            mech, &mechparams, wincx);
1160
0
}
1161
1162
static SECStatus
1163
vfy_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
1164
               const SECItem *sig, SECOidTag encAlg, SECOidTag hashAlg,
1165
               CK_MECHANISM_TYPE mech, SECItem *mechparamsp,
1166
               SECOidTag *hash, void *wincx)
1167
0
{
1168
0
    SECStatus rv;
1169
0
    VFYContext *cx;
1170
1171
0
    cx = vfy_CreateContext(key, sig, encAlg, hashAlg, mech, mechparamsp,
1172
0
                           hash, PR_FALSE, wincx);
1173
0
    if (cx == NULL)
1174
0
        return SECFailure;
1175
1176
0
    rv = vfy_SingleShot(cx, buf, len);
1177
1178
0
    VFY_DestroyContext(cx, PR_TRUE);
1179
0
    return rv;
1180
0
}
1181
1182
SECStatus
1183
VFY_VerifyDataDirect(const unsigned char *buf, int len,
1184
                     const SECKEYPublicKey *key, const SECItem *sig,
1185
                     SECOidTag encAlg, SECOidTag hashAlg,
1186
                     SECOidTag *hash, void *wincx)
1187
0
{
1188
0
    CK_MECHANISM_TYPE mech = sec_GetCombinedMech(encAlg, hashAlg);
1189
0
    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech, NULL,
1190
0
                          hash, wincx);
1191
0
}
1192
1193
SECStatus
1194
VFY_VerifyData(const unsigned char *buf, int len, const SECKEYPublicKey *key,
1195
               const SECItem *sig, SECOidTag algid, void *wincx)
1196
0
{
1197
0
    SECOidTag encAlg, hashAlg;
1198
0
    CK_MECHANISM_TYPE mech;
1199
0
    SECItem mechparams;
1200
0
    SECStatus rv = sec_DecodeSigAlg(key, algid, NULL, &encAlg, &hashAlg,
1201
0
                                    &mech, &mechparams);
1202
0
    if (rv != SECSuccess) {
1203
0
        return rv;
1204
0
    }
1205
0
    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg,
1206
0
                          mech, &mechparams, NULL, wincx);
1207
0
}
1208
1209
SECStatus
1210
VFY_VerifyDataWithAlgorithmID(const unsigned char *buf, int len,
1211
                              const SECKEYPublicKey *key,
1212
                              const SECItem *sig,
1213
                              const SECAlgorithmID *sigAlgorithm,
1214
                              SECOidTag *hash, void *wincx)
1215
0
{
1216
0
    SECOidTag encAlg, hashAlg;
1217
0
    SECOidTag sigAlg = SECOID_GetAlgorithmTag((SECAlgorithmID *)sigAlgorithm);
1218
0
    CK_MECHANISM_TYPE mech;
1219
0
    SECItem mechparams;
1220
0
    SECStatus rv = sec_DecodeSigAlg(key, sigAlg,
1221
0
                                    &sigAlgorithm->parameters, &encAlg, &hashAlg,
1222
0
                                    &mech, &mechparams);
1223
0
    if (rv != SECSuccess) {
1224
0
        return rv;
1225
0
    }
1226
0
    return vfy_VerifyData(buf, len, key, sig, encAlg, hashAlg, mech,
1227
0
                          &mechparams, hash, wincx);
1228
0
}