aboutsummaryrefslogtreecommitdiffstats
path: root/main/nss/CVE-2012-0441.patch
blob: bfb102f1c9dce30a8450270364b203af97a17182 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
Index: nss/mozilla/security/nss/lib/softoken/legacydb/keydb.c
===================================================================
--- nss.orig/mozilla/security/nss/lib/softoken/legacydb/keydb.c	2012-06-02 09:40:33.313201758 +0200
+++ nss/mozilla/security/nss/lib/softoken/legacydb/keydb.c	2012-06-02 09:44:24.107462120 +0200
@@ -1790,6 +1790,35 @@
 		rv = SEC_QuickDERDecodeItem(permarena, pk,
 					nsslowkey_RSAPrivateKeyTemplate,
 					&newPrivateKey);
+		if (rv == SECSuccess) {
+		    break;
+		}
+		/* Try decoding with the alternative template, but only allow
+		 * a zero-length modulus for a secret key object.
+		 * See bug 715073.
+		 */
+		rv = SEC_QuickDERDecodeItem(permarena, pk,
+					nsslowkey_RSAPrivateKeyTemplate2,
+					&newPrivateKey);
+		/* A publicExponent of 0 is the defining property of a secret
+		 * key disguised as an RSA key. When decoding with the
+		 * alternative template, only accept a secret key with an
+		 * improperly encoded modulus and a publicExponent of 0.
+		 */
+		if (rv == SECSuccess) {
+		    if (pk->u.rsa.modulus.len == 2 &&
+			pk->u.rsa.modulus.data[0] == SEC_ASN1_INTEGER &&
+			pk->u.rsa.modulus.data[1] == 0 &&
+			pk->u.rsa.publicExponent.len == 1 &&
+			pk->u.rsa.publicExponent.data[0] == 0) {
+			/* Fix the zero-length integer by setting it to 0. */
+			pk->u.rsa.modulus.data = pk->u.rsa.publicExponent.data;
+			pk->u.rsa.modulus.len = pk->u.rsa.publicExponent.len;
+		    } else {
+			PORT_SetError(SEC_ERROR_BAD_DER);
+			rv = SECFailure;
+		    }
+		}
 		break;
 	      case SEC_OID_ANSIX9_DSA_SIGNATURE:
 		pk->keyType = NSSLOWKEYDSAKey;
Index: nss/mozilla/security/nss/lib/softoken/legacydb/lgcreate.c
===================================================================
--- nss.orig/mozilla/security/nss/lib/softoken/legacydb/lgcreate.c	2012-06-02 09:40:33.313201758 +0200
+++ nss/mozilla/security/nss/lib/softoken/legacydb/lgcreate.c	2012-06-02 09:42:35.354166672 +0200
@@ -818,11 +818,16 @@
     privKey->keyType = NSSLOWKEYRSAKey;
 
     /* The modulus is set to the key id of the symmetric key */
-    crv = lg_Attribute2SecItem(arena, CKA_ID, templ, count, 
-				&privKey->u.rsa.modulus);
-    if (crv != CKR_OK) goto loser;
+    privKey->u.rsa.modulus.data =
+		(unsigned char *) PORT_ArenaAlloc(arena, pubkey->len);
+    if (privKey->u.rsa.modulus.data == NULL) {
+	crv = CKR_HOST_MEMORY;
+	goto loser;
+    }
+    privKey->u.rsa.modulus.len = pubkey->len;
+    PORT_Memcpy(privKey->u.rsa.modulus.data, pubkey->data, pubkey->len);
 
-    /* The public exponent is set to 0 length to indicate a special key */
+    /* The public exponent is set to 0 to indicate a special key */
     privKey->u.rsa.publicExponent.len = sizeof derZero;
     privKey->u.rsa.publicExponent.data = derZero;
 
Index: nss/mozilla/security/nss/lib/softoken/legacydb/lowkey.c
===================================================================
--- nss.orig/mozilla/security/nss/lib/softoken/legacydb/lowkey.c	2012-06-02 09:40:33.317201659 +0200
+++ nss/mozilla/security/nss/lib/softoken/legacydb/lowkey.c	2012-06-02 09:45:10.962296923 +0200
@@ -97,6 +97,24 @@
     { 0 }                                                                     
 };                                                                            
 
+/*
+ * Allows u.rsa.modulus to be zero length for secret keys with an empty
+ * CKA_ID incorrectly generated in NSS 3.13.3 or earlier.  Only used for
+ * decoding.  See bug 715073.
+ */
+const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate2[] = {
+    { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.version) },
+    { SEC_ASN1_ANY, offsetof(NSSLOWKEYPrivateKey,u.rsa.modulus) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.publicExponent) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.privateExponent) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime1) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.prime2) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent1) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.exponent2) },
+    { SEC_ASN1_INTEGER, offsetof(NSSLOWKEYPrivateKey,u.rsa.coefficient) },
+    { 0 }
+};
 
 const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[] = {
     { SEC_ASN1_SEQUENCE, 0, NULL, sizeof(NSSLOWKEYPrivateKey) },
Index: nss/mozilla/security/nss/lib/softoken/legacydb/lowkeyti.h
===================================================================
--- nss.orig/mozilla/security/nss/lib/softoken/legacydb/lowkeyti.h	2012-06-02 09:40:33.317201659 +0200
+++ nss/mozilla/security/nss/lib/softoken/legacydb/lowkeyti.h	2012-06-02 09:43:25.700914607 +0200
@@ -72,6 +72,7 @@
 */
 extern const SEC_ASN1Template nsslowkey_PQGParamsTemplate[];
 extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate[];
+extern const SEC_ASN1Template nsslowkey_RSAPrivateKeyTemplate2[];
 extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyTemplate[];
 extern const SEC_ASN1Template nsslowkey_DSAPrivateKeyExportTemplate[];
 extern const SEC_ASN1Template nsslowkey_DHPrivateKeyTemplate[];
Index: nss/mozilla/security/nss/lib/util/quickder.c
===================================================================
--- nss.orig/mozilla/security/nss/lib/util/quickder.c	2012-06-02 09:40:33.341201062 +0200
+++ nss/mozilla/security/nss/lib/util/quickder.c	2012-06-02 09:42:36.418140213 +0200
@@ -815,40 +815,57 @@
             SECItem newtemp = temp;
             rv = GetItem(&newtemp, &temp, PR_FALSE);
             save = PR_TRUE;
-            if ((SECSuccess == rv) && SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK))
-            switch (kind & SEC_ASN1_TAGNUM_MASK)
+            if ((SECSuccess == rv) &&
+                SEC_ASN1_UNIVERSAL == (kind & SEC_ASN1_CLASS_MASK))
             {
-            /* special cases of primitive types */
-            case SEC_ASN1_INTEGER:
+                unsigned long tagnum = kind & SEC_ASN1_TAGNUM_MASK;
+                if ( temp.len == 0 && (tagnum == SEC_ASN1_BOOLEAN ||
+                                       tagnum == SEC_ASN1_INTEGER ||
+                                       tagnum == SEC_ASN1_BIT_STRING ||
+                                       tagnum == SEC_ASN1_OBJECT_ID ||
+                                       tagnum == SEC_ASN1_ENUMERATED ||
+                                       tagnum == SEC_ASN1_UTC_TIME ||
+                                       tagnum == SEC_ASN1_GENERALIZED_TIME) )
                 {
-                    /* remove leading zeroes if the caller requested siUnsignedInteger
-                       This is to allow RSA key operations to work */
-                    SECItem* destItem = (SECItem*) ((char*)dest + templateEntry->offset);
-                    if (destItem && (siUnsignedInteger == destItem->type))
+                    /* these types MUST have at least one content octet */
+                    PORT_SetError(SEC_ERROR_BAD_DER);
+                    rv = SECFailure;
+                }
+                else
+                switch (tagnum)
+                {
+                /* special cases of primitive types */
+                case SEC_ASN1_INTEGER:
                     {
-                        while (temp.len > 1 && temp.data[0] == 0)
-                        {              /* leading 0 */
-                            temp.data++;
-                            temp.len--;
+                        /* remove leading zeroes if the caller requested
+                           siUnsignedInteger
+                           This is to allow RSA key operations to work */
+                        SECItem* destItem = (SECItem*) ((char*)dest +
+                                            templateEntry->offset);
+                        if (destItem && (siUnsignedInteger == destItem->type))
+                        {
+                            while (temp.len > 1 && temp.data[0] == 0)
+                            {              /* leading 0 */
+                                temp.data++;
+                                temp.len--;
+                            }
                         }
+                        break;
                     }
-                    break;
-                }
 
-            case SEC_ASN1_BIT_STRING:
-                {
-                    /* change the length in the SECItem to be the number of bits */
-                    if (temp.len && temp.data)
+                case SEC_ASN1_BIT_STRING:
                     {
-                        temp.len = (temp.len-1)*8 - ((*(unsigned char*)temp.data) & 0x7);
-                        temp.data = (unsigned char*)(temp.data+1);
+                        /* change the length in the SECItem to be the number
+                           of bits */
+                        temp.len = (temp.len-1)*8 - (temp.data[0] & 0x7);
+                        temp.data++;
+                        break;
                     }
-                    break;
-                }
 
-            default:
-                {
-                    break;
+                default:
+                    {
+                        break;
+                    }
                 }
             }
         }
@@ -863,7 +880,7 @@
                If part of the destination was allocated by the decoder, in
                cases of POINTER, SET OF and SEQUENCE OF, then type is set to
                siBuffer due to the use of PORT_ArenaZAlloc*/
-            destItem->data = temp.data;
+            destItem->data = temp.len ? temp.data : NULL;
             destItem->len = temp.len;
         }
         else