Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/util/derdec.c @ 0:1e5118fa0cb1
This is NSS with a Cmake Buildsyste
To compile a static NSS library for Windows we've used the
Chromium-NSS fork and added a Cmake buildsystem to compile
it statically for Windows. See README.chromium for chromium
changes and README.trustbridge for our modifications.
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Mon, 28 Jul 2014 10:47:06 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:1e5118fa0cb1 |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | |
4 | |
5 #include "secder.h" | |
6 #include "secerr.h" | |
7 | |
8 static PRUint32 | |
9 der_indefinite_length(unsigned char *buf, unsigned char *end) | |
10 { | |
11 PRUint32 len, ret, dataLen; | |
12 unsigned char tag, lenCode; | |
13 int dataLenLen; | |
14 | |
15 len = 0; | |
16 while ( 1 ) { | |
17 if ((buf + 2) > end) { | |
18 return(0); | |
19 } | |
20 | |
21 tag = *buf++; | |
22 lenCode = *buf++; | |
23 len += 2; | |
24 | |
25 if ( ( tag == 0 ) && ( lenCode == 0 ) ) { | |
26 return(len); | |
27 } | |
28 | |
29 if ( lenCode == 0x80 ) { /* indefinite length */ | |
30 ret = der_indefinite_length(buf, end); /* recurse to find length */ | |
31 if (ret == 0) | |
32 return 0; | |
33 len += ret; | |
34 buf += ret; | |
35 } else { /* definite length */ | |
36 if (lenCode & 0x80) { | |
37 /* Length of data is in multibyte format */ | |
38 dataLenLen = lenCode & 0x7f; | |
39 switch (dataLenLen) { | |
40 case 1: | |
41 dataLen = buf[0]; | |
42 break; | |
43 case 2: | |
44 dataLen = (buf[0]<<8)|buf[1]; | |
45 break; | |
46 case 3: | |
47 dataLen = ((unsigned long)buf[0]<<16)|(buf[1]<<8)|buf[2]; | |
48 break; | |
49 case 4: | |
50 dataLen = ((unsigned long)buf[0]<<24)| | |
51 ((unsigned long)buf[1]<<16)|(buf[2]<<8)|buf[3]; | |
52 break; | |
53 default: | |
54 PORT_SetError(SEC_ERROR_BAD_DER); | |
55 return SECFailure; | |
56 } | |
57 } else { | |
58 /* Length of data is in single byte */ | |
59 dataLen = lenCode; | |
60 dataLenLen = 0; | |
61 } | |
62 | |
63 /* skip this item */ | |
64 buf = buf + dataLenLen + dataLen; | |
65 len = len + dataLenLen + dataLen; | |
66 } | |
67 } | |
68 } | |
69 | |
70 /* | |
71 ** Capture the next thing in the buffer. | |
72 ** Returns the length of the header and the length of the contents. | |
73 */ | |
74 static SECStatus | |
75 der_capture(unsigned char *buf, unsigned char *end, | |
76 int *header_len_p, PRUint32 *contents_len_p) | |
77 { | |
78 unsigned char *bp; | |
79 unsigned char whole_tag; | |
80 PRUint32 contents_len; | |
81 int tag_number; | |
82 | |
83 if ((buf + 2) > end) { | |
84 *header_len_p = 0; | |
85 *contents_len_p = 0; | |
86 if (buf == end) | |
87 return SECSuccess; | |
88 return SECFailure; | |
89 } | |
90 | |
91 bp = buf; | |
92 | |
93 /* Get tag and verify that it is ok. */ | |
94 whole_tag = *bp++; | |
95 tag_number = whole_tag & DER_TAGNUM_MASK; | |
96 | |
97 /* | |
98 * XXX This code does not (yet) handle the high-tag-number form! | |
99 */ | |
100 if (tag_number == DER_HIGH_TAG_NUMBER) { | |
101 PORT_SetError(SEC_ERROR_BAD_DER); | |
102 return SECFailure; | |
103 } | |
104 | |
105 if ((whole_tag & DER_CLASS_MASK) == DER_UNIVERSAL) { | |
106 /* Check that the universal tag number is one we implement. */ | |
107 switch (tag_number) { | |
108 case DER_BOOLEAN: | |
109 case DER_INTEGER: | |
110 case DER_BIT_STRING: | |
111 case DER_OCTET_STRING: | |
112 case DER_NULL: | |
113 case DER_OBJECT_ID: | |
114 case DER_SEQUENCE: | |
115 case DER_SET: | |
116 case DER_PRINTABLE_STRING: | |
117 case DER_T61_STRING: | |
118 case DER_IA5_STRING: | |
119 case DER_VISIBLE_STRING: | |
120 case DER_UTC_TIME: | |
121 case 0: /* end-of-contents tag */ | |
122 break; | |
123 default: | |
124 PORT_SetError(SEC_ERROR_BAD_DER); | |
125 return SECFailure; | |
126 } | |
127 } | |
128 | |
129 /* | |
130 * Get first byte of length code (might contain entire length, might not). | |
131 */ | |
132 contents_len = *bp++; | |
133 | |
134 /* | |
135 * If the high bit is set, then the length is in multibyte format, | |
136 * or the thing has an indefinite-length. | |
137 */ | |
138 if (contents_len & 0x80) { | |
139 int bytes_of_encoded_len; | |
140 | |
141 bytes_of_encoded_len = contents_len & 0x7f; | |
142 contents_len = 0; | |
143 | |
144 switch (bytes_of_encoded_len) { | |
145 case 4: | |
146 contents_len |= *bp++; | |
147 contents_len <<= 8; | |
148 /* fallthru */ | |
149 case 3: | |
150 contents_len |= *bp++; | |
151 contents_len <<= 8; | |
152 /* fallthru */ | |
153 case 2: | |
154 contents_len |= *bp++; | |
155 contents_len <<= 8; | |
156 /* fallthru */ | |
157 case 1: | |
158 contents_len |= *bp++; | |
159 break; | |
160 | |
161 case 0: | |
162 contents_len = der_indefinite_length (bp, end); | |
163 if (contents_len) | |
164 break; | |
165 /* fallthru */ | |
166 default: | |
167 PORT_SetError(SEC_ERROR_BAD_DER); | |
168 return SECFailure; | |
169 } | |
170 } | |
171 | |
172 if ((bp + contents_len) > end) { | |
173 /* Ran past end of buffer */ | |
174 PORT_SetError(SEC_ERROR_BAD_DER); | |
175 return SECFailure; | |
176 } | |
177 | |
178 *header_len_p = bp - buf; | |
179 *contents_len_p = contents_len; | |
180 | |
181 return SECSuccess; | |
182 } | |
183 | |
184 SECStatus | |
185 DER_Lengths(SECItem *item, int *header_len_p, PRUint32 *contents_len_p) | |
186 { | |
187 return(der_capture(item->data, &item->data[item->len], header_len_p, | |
188 contents_len_p)); | |
189 } |