2 * PKCS#1 encoding and decoding functions.
3 * This file is believed to contain no code licensed from other parties.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
13 /* Needed for RSA-PSS functions */
14 static const unsigned char eightZeros
[] = { 0, 0, 0, 0, 0, 0, 0, 0 };
17 * Mask generation function MGF1 as defined in PKCS #1 v2.1 / RFC 3447.
20 MGF1(HASH_HashType hashAlg
, unsigned char *mask
, unsigned int maskLen
,
21 const unsigned char *mgfSeed
, unsigned int mgfSeedLen
)
23 unsigned int digestLen
;
24 PRUint32 counter
, rounds
;
25 unsigned char *tempHash
, *temp
;
26 const SECHashObject
*hash
;
30 hash
= HASH_GetHashObject(hashAlg
);
34 hashContext
= (*hash
->create
)();
35 rounds
= (maskLen
+ hash
->length
- 1) / hash
->length
;
36 for (counter
= 0; counter
< rounds
; counter
++) {
37 C
[0] = (unsigned char)((counter
>> 24) & 0xff);
38 C
[1] = (unsigned char)((counter
>> 16) & 0xff);
39 C
[2] = (unsigned char)((counter
>> 8) & 0xff);
40 C
[3] = (unsigned char)(counter
& 0xff);
42 /* This could be optimized when the clone functions in
43 * rawhash.c are implemented. */
44 (*hash
->begin
)(hashContext
);
45 (*hash
->update
)(hashContext
, mgfSeed
, mgfSeedLen
);
46 (*hash
->update
)(hashContext
, C
, sizeof C
);
48 tempHash
= mask
+ counter
* hash
->length
;
49 if (counter
!= (rounds
-1)) {
50 (*hash
->end
)(hashContext
, tempHash
, &digestLen
, hash
->length
);
51 } else { /* we're in the last round and need to cut the hash */
52 temp
= (unsigned char *)PORT_Alloc(hash
->length
);
53 (*hash
->end
)(hashContext
, temp
, &digestLen
, hash
->length
);
54 PORT_Memcpy(tempHash
, temp
, maskLen
- counter
* hash
->length
);
58 (*hash
->destroy
)(hashContext
, PR_TRUE
);
64 * Verify a RSA-PSS signature.
65 * Described in RFC 3447, section 9.1.2.
66 * We use mHash instead of M as input.
67 * emBits from the RFC is just modBits - 1, see section 8.1.2.
68 * We only support MGF1 as the MGF.
70 * NOTE: this code assumes modBits is a multiple of 8.
73 emsa_pss_verify(const unsigned char *mHash
,
74 const unsigned char *em
, unsigned int emLen
,
75 HASH_HashType hashAlg
, HASH_HashType maskHashAlg
,
78 const SECHashObject
*hash
;
81 unsigned char *H_
; /* H' from the RFC */
82 unsigned int i
, dbMaskLen
;
85 hash
= HASH_GetHashObject(hashAlg
);
86 dbMaskLen
= emLen
- hash
->length
- 1;
89 if ((emLen
< (hash
->length
+ sLen
+ 2)) ||
90 (em
[emLen
- 1] != 0xbc) ||
91 ((em
[0] & 0x80) != 0)) {
92 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
97 db
= (unsigned char *)PORT_Alloc(dbMaskLen
);
99 PORT_SetError(SEC_ERROR_NO_MEMORY
);
102 /* &em[dbMaskLen] points to H, used as mgfSeed */
103 MGF1(maskHashAlg
, db
, dbMaskLen
, &em
[dbMaskLen
], hash
->length
);
106 for (i
= 0; i
< dbMaskLen
; i
++) {
114 for (i
= 0; i
< (dbMaskLen
- sLen
- 1); i
++) {
117 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
121 if (db
[dbMaskLen
- sLen
- 1] != 0x01) {
123 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);
128 H_
= (unsigned char *)PORT_Alloc(hash
->length
);
131 PORT_SetError(SEC_ERROR_NO_MEMORY
);
134 hash_context
= (*hash
->create
)();
135 if (hash_context
== NULL
) {
138 PORT_SetError(SEC_ERROR_NO_MEMORY
);
141 (*hash
->begin
)(hash_context
);
142 (*hash
->update
)(hash_context
, eightZeros
, 8);
143 (*hash
->update
)(hash_context
, mHash
, hash
->length
);
144 (*hash
->update
)(hash_context
, &db
[dbMaskLen
- sLen
], sLen
);
145 (*hash
->end
)(hash_context
, H_
, &i
, hash
->length
);
146 (*hash
->destroy
)(hash_context
, PR_TRUE
);
151 if (PORT_Memcmp(H_
, &em
[dbMaskLen
], hash
->length
) != 0) {
152 PORT_SetError(SEC_ERROR_BAD_SIGNATURE
);