File: | lib/x509/common.c |
Location: | line 662, column 8 |
Description: | Although the value stored to 'result' is used in the enclosing expression, the value is never actually read from 'result' |
1 | /* |
2 | * Copyright (C) 2003-2012 Free Software Foundation, Inc. |
3 | * |
4 | * Author: Nikos Mavrogiannopoulos |
5 | * |
6 | * This file is part of GnuTLS. |
7 | * |
8 | * The GnuTLS is free software; you can redistribute it and/or |
9 | * modify it under the terms of the GNU Lesser General Public License |
10 | * as published by the Free Software Foundation; either version 3 of |
11 | * the License, or (at your option) any later version. |
12 | * |
13 | * This library is distributed in the hope that it will be useful, but |
14 | * WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
16 | * Lesser General Public License for more details. |
17 | * |
18 | * You should have received a copy of the GNU Lesser General Public License |
19 | * along with this program. If not, see <http://www.gnu.org/licenses/> |
20 | * |
21 | */ |
22 | |
23 | #include <gnutls_int.h> |
24 | #include <libtasn1.h> |
25 | #include <gnutls_datumgnutls_datum_t.h> |
26 | #include <gnutls_global.h> |
27 | #include <gnutls_errors.h> |
28 | #include <gnutls_str.h> |
29 | #include <gnutls_x509.h> |
30 | #include <gnutls_num.h> |
31 | #include <x509_b64.h> |
32 | #include "x509_int.h" |
33 | #include <common.h> |
34 | |
35 | struct oid2string |
36 | { |
37 | const char *oid; |
38 | const char *ldap_desc; |
39 | int choice; /* of type DirectoryString */ |
40 | int printable; |
41 | const char *asn_desc; /* description in the pkix file */ |
42 | }; |
43 | |
44 | /* This list contains all the OIDs that may be |
45 | * contained in a rdnSequence and are printable. |
46 | */ |
47 | static const struct oid2string _oid2str[] = { |
48 | /* PKIX |
49 | */ |
50 | {"1.3.6.1.5.5.7.9.1", "dateOfBirth", 0, 1, "PKIX1.GeneralizedTime"}, |
51 | {"1.3.6.1.5.5.7.9.2", "placeOfBirth", 0, 1, "PKIX1.DirectoryString"}, |
52 | {"1.3.6.1.5.5.7.9.3", "gender", 0, 1, "PKIX1.PrintableString"}, |
53 | {"1.3.6.1.5.5.7.9.4", "countryOfCitizenship", 0, 1, |
54 | "PKIX1.PrintableString"}, |
55 | {"1.3.6.1.5.5.7.9.5", "countryOfResidence", 0, 1, "PKIX1.PrintableString"}, |
56 | |
57 | {"2.5.4.6", "C", 0, 1, "PKIX1.PrintableString"}, |
58 | {"2.5.4.9", "STREET", 1, 1, "PKIX1.DirectoryString"}, |
59 | {"2.5.4.12", "T", 1, 1, "PKIX1.DirectoryString"}, |
60 | {"2.5.4.10", "O", 1, 1, "PKIX1.DirectoryString"}, |
61 | {"2.5.4.11", "OU", 1, 1, "PKIX1.DirectoryString"}, |
62 | {"2.5.4.3", "CN", 1, 1, "PKIX1.DirectoryString"}, |
63 | {"2.5.4.7", "L", 1, 1, "PKIX1.DirectoryString"}, |
64 | {"2.5.4.8", "ST", 1, 1, "PKIX1.DirectoryString"}, |
65 | |
66 | {"2.5.4.5", "serialNumber", 0, 1, "PKIX1.PrintableString"}, |
67 | {"2.5.4.20", "telephoneNumber", 0, 1, "PKIX1.PrintableString"}, |
68 | {"2.5.4.4", "surName", 1, 1, "PKIX1.DirectoryString"}, |
69 | {"2.5.4.43", "initials", 1, 1, "PKIX1.DirectoryString"}, |
70 | {"2.5.4.44", "generationQualifier", 1, 1, "PKIX1.DirectoryString"}, |
71 | {"2.5.4.42", "givenName", 1, 1, "PKIX1.DirectoryString"}, |
72 | {"2.5.4.65", "pseudonym", 1, 1, "PKIX1.DirectoryString"}, |
73 | {"2.5.4.46", "dnQualifier", 0, 1, "PKIX1.PrintableString"}, |
74 | {"2.5.4.17", "postalCode", 1, 1, "PKIX1.DirectoryString"}, |
75 | {"2.5.4.41", "Name", 1, 1, "PKIX1.DirectoryString"}, |
76 | {"2.5.4.15", "businessCategory", 1, 1, "PKIX1.DirectoryString"}, |
77 | |
78 | {"0.9.2342.19200300.100.1.25", "DC", 0, 1, "PKIX1.IA5String"}, |
79 | {"0.9.2342.19200300.100.1.1", "UID", 1, 1, "PKIX1.DirectoryString"}, |
80 | |
81 | /* Extended validation |
82 | */ |
83 | {"1.3.6.1.4.1.311.60.2.1.1", "jurisdictionOfIncorporationLocalityName", 1, |
84 | 1, "PKIX1.DirectoryString"}, |
85 | {"1.3.6.1.4.1.311.60.2.1.2", |
86 | "jurisdictionOfIncorporationStateOrProvinceName", 1, 1, |
87 | "PKIX1.DirectoryString"}, |
88 | {"1.3.6.1.4.1.311.60.2.1.3", "jurisdictionOfIncorporationCountryName", 0, 1, |
89 | "PKIX1.PrintableString"}, |
90 | |
91 | /* PKCS #9 |
92 | */ |
93 | {"1.2.840.113549.1.9.1", "EMAIL", 0, 1, "PKIX1.IA5String"}, |
94 | {"1.2.840.113549.1.9.7", NULL((void*)0), 1, 1, "PKIX1.pkcs-9-challengePassword"}, |
95 | |
96 | /* friendly name */ |
97 | {"1.2.840.113549.1.9.20", NULL((void*)0), 0, 1, "PKIX1.BMPString"}, |
98 | /* local key id */ |
99 | {"1.2.840.113549.1.9.21", NULL((void*)0), 0, 1, "PKIX1.pkcs-9-localKeyId"}, |
100 | |
101 | /* rfc3920 section 5.1.1 */ |
102 | {"1.3.6.1.5.5.7.8.5", "XmppAddr", 0, 1, "PKIX1.UTF8String"}, |
103 | |
104 | {NULL((void*)0), NULL((void*)0), 0, 0, ""} |
105 | }; |
106 | |
107 | /* Returns 1 if the data defined by the OID are printable. |
108 | */ |
109 | int |
110 | _gnutls_x509_oid_data_printable (const char *oid) |
111 | { |
112 | int i = 0; |
113 | |
114 | do |
115 | { |
116 | if (strcmp (_oid2str[i].oid, oid) == 0) |
117 | return _oid2str[i].printable; |
118 | i++; |
119 | } |
120 | while (_oid2str[i].oid != NULL((void*)0)); |
121 | |
122 | return 0; |
123 | } |
124 | |
125 | /** |
126 | * gnutls_x509_dn_oid_known: |
127 | * @oid: holds an Object Identifier in a null terminated string |
128 | * |
129 | * This function will inform about known DN OIDs. This is useful since |
130 | * functions like gnutls_x509_crt_set_dn_by_oid() use the information |
131 | * on known OIDs to properly encode their input. Object Identifiers |
132 | * that are not known are not encoded by these functions, and their |
133 | * input is stored directly into the ASN.1 structure. In that case of |
134 | * unknown OIDs, you have the responsibility of DER encoding your |
135 | * data. |
136 | * |
137 | * Returns: 1 on known OIDs and 0 otherwise. |
138 | **/ |
139 | int |
140 | gnutls_x509_dn_oid_known (const char *oid) |
141 | { |
142 | int i = 0; |
143 | |
144 | do |
145 | { |
146 | if (strcmp (_oid2str[i].oid, oid) == 0) |
147 | return 1; |
148 | i++; |
149 | } |
150 | while (_oid2str[i].oid != NULL((void*)0)); |
151 | |
152 | return 0; |
153 | } |
154 | |
155 | /* Returns 1 if the data defined by the OID are of a choice |
156 | * type. |
157 | */ |
158 | int |
159 | _gnutls_x509_oid_data_choice (const char *oid) |
160 | { |
161 | int i = 0; |
162 | |
163 | do |
164 | { |
165 | if (strcmp (_oid2str[i].oid, oid) == 0) |
166 | return _oid2str[i].choice; |
167 | i++; |
168 | } |
169 | while (_oid2str[i].oid != NULL((void*)0)); |
170 | |
171 | return 0; |
172 | } |
173 | |
174 | /** |
175 | * gnutls_x509_dn_oid_name: |
176 | * @oid: holds an Object Identifier in a null terminated string |
177 | * @flags: 0 or %GNUTLS_X509_DN_OID_* |
178 | * |
179 | * This function will return the name of a known DN OID. If |
180 | * %GNUTLS_X509_DN_OID_RETURN_OID is specified this function |
181 | * will return the given OID if no descriptive name has been |
182 | * found. |
183 | * |
184 | * Returns: A null terminated string or NULL otherwise. |
185 | * |
186 | * Since: 3.0.0 |
187 | **/ |
188 | const char* |
189 | gnutls_x509_dn_oid_name (const char *oid, unsigned int flags) |
190 | { |
191 | int i = 0; |
192 | |
193 | do |
194 | { |
195 | if (strcmp (_oid2str[i].oid, oid) == 0) |
196 | return _oid2str[i].ldap_desc; |
197 | i++; |
198 | } |
199 | while (_oid2str[i].oid != NULL((void*)0)); |
200 | |
201 | if (flags & GNUTLS_X509_DN_OID_RETURN_OID1) return oid; |
202 | else return NULL((void*)0); |
203 | } |
204 | |
205 | const char * |
206 | _gnutls_x509_oid2asn_string (const char *oid) |
207 | { |
208 | int i = 0; |
209 | |
210 | do |
211 | { |
212 | if (strcmp (_oid2str[i].oid, oid) == 0) |
213 | return _oid2str[i].asn_desc; |
214 | i++; |
215 | } |
216 | while (_oid2str[i].oid != NULL((void*)0)); |
217 | |
218 | return NULL((void*)0); |
219 | } |
220 | |
221 | |
222 | /* This function will convert an attribute value, specified by the OID, |
223 | * to a string. The result will be a null terminated string. |
224 | * |
225 | * res may be null. This will just return the res_size, needed to |
226 | * hold the string. |
227 | */ |
228 | int |
229 | _gnutls_x509_oid_data2string (const char *oid, void *value, |
230 | int value_size, char *res, size_t * res_size) |
231 | { |
232 | char str[MAX_STRING_LEN512], tmpname[128]; |
233 | const char *ANAME = NULL((void*)0); |
234 | int CHOICE = -1, len = -1, result; |
235 | ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY((void*)0); |
236 | char asn1_err[ASN1_MAX_ERROR_DESCRIPTION_SIZE128] = ""; |
237 | |
238 | if (value == NULL((void*)0) || value_size <= 0 || res_size == NULL((void*)0)) |
239 | { |
240 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",240); } while(0);; |
241 | return GNUTLS_E_INVALID_REQUEST-50; |
242 | } |
243 | |
244 | if (_gnutls_x509_oid_data_printable (oid) == 0) |
245 | { |
246 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",246); } while(0);; |
247 | return GNUTLS_E_INTERNAL_ERROR-59; |
248 | } |
249 | |
250 | ANAME = _gnutls_x509_oid2asn_string (oid); |
251 | CHOICE = _gnutls_x509_oid_data_choice (oid); |
252 | |
253 | if (ANAME == NULL((void*)0)) |
254 | { |
255 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",255); } while(0);; |
256 | return GNUTLS_E_INTERNAL_ERROR-59; |
257 | } |
258 | |
259 | if ((result = |
260 | asn1_create_element (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), ANAME, |
261 | &tmpasn)) != ASN1_SUCCESS0) |
262 | { |
263 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",263); } while(0);; |
264 | return _gnutls_asn2err (result); |
265 | } |
266 | |
267 | if ((result = |
268 | asn1_der_decoding (&tmpasn, value, value_size, |
269 | asn1_err)) != ASN1_SUCCESS0) |
270 | { |
271 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",271); } while(0);; |
272 | _gnutls_debug_log ("asn1_der_decoding: %s:%s\n", str, asn1_err)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "asn1_der_decoding: %s:%s\n", str, asn1_err); } while(0); |
273 | asn1_delete_structure (&tmpasn); |
274 | return _gnutls_asn2err (result); |
275 | } |
276 | |
277 | /* If this is a choice then we read the choice. Otherwise it |
278 | * is the value; |
279 | */ |
280 | len = sizeof (str) - 1; |
281 | if ((result = asn1_read_value (tmpasn, "", str, &len)) != ASN1_SUCCESS0) |
282 | { /* CHOICE */ |
283 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",283); } while(0);; |
284 | asn1_delete_structure (&tmpasn); |
285 | return _gnutls_asn2err (result); |
286 | } |
287 | |
288 | if (CHOICE == 0) |
289 | { |
290 | str[len] = 0; |
291 | |
292 | /* Refuse to deal with strings containing NULs. */ |
293 | if (strlen (str) != len) |
294 | return GNUTLS_E_ASN1_DER_ERROR-69; |
295 | |
296 | if (res) |
297 | _gnutls_str_cpy (res, *res_size, str); |
298 | *res_size = len; |
299 | |
300 | asn1_delete_structure (&tmpasn); |
301 | } |
302 | else |
303 | { /* CHOICE */ |
304 | int non_printable = 0, teletex = 0; |
305 | str[len] = 0; |
306 | |
307 | /* Note that we do not support strings other than |
308 | * UTF-8 (thus ASCII as well). |
309 | */ |
310 | if (strcmp (str, "printableString") != 0 && |
311 | strcmp (str, "ia5String") != 0 && strcmp (str, "utf8String") != 0) |
312 | { |
313 | non_printable = 1; |
314 | } |
315 | if (strcmp (str, "teletexString") == 0) |
316 | teletex = 1; |
317 | |
318 | |
319 | _gnutls_str_cpy (tmpname, sizeof (tmpname), str); |
320 | |
321 | len = sizeof (str) - 1; |
322 | if ((result = |
323 | asn1_read_value (tmpasn, tmpname, str, &len)) != ASN1_SUCCESS0) |
324 | { |
325 | asn1_delete_structure (&tmpasn); |
326 | return _gnutls_asn2err (result); |
327 | } |
328 | |
329 | asn1_delete_structure (&tmpasn); |
330 | |
331 | if (teletex != 0) |
332 | { |
333 | int ascii = 0, i; |
334 | /* HACK: if the teletex string contains only ascii |
335 | * characters then treat it as printable. |
336 | */ |
337 | for (i = 0; i < len; i++) |
338 | if (!isascii (str[i])(((str[i]) & ~0x7f) == 0)) |
339 | ascii = 1; |
340 | |
341 | if (ascii == 0) |
342 | non_printable = 0; |
343 | } |
344 | |
345 | if (non_printable == 0) |
346 | { |
347 | str[len] = 0; |
348 | |
349 | /* Refuse to deal with strings containing NULs. */ |
350 | if (strlen (str) != len) |
351 | return GNUTLS_E_ASN1_DER_ERROR-69; |
352 | |
353 | if (res) |
354 | _gnutls_str_cpy (res, *res_size, str); |
355 | *res_size = len; |
356 | } |
357 | else |
358 | { |
359 | result = _gnutls_x509_data2hex (str, len, res, res_size); |
360 | if (result < 0) |
361 | { |
362 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",362); } while(0);; |
363 | return result; |
364 | } |
365 | } |
366 | } |
367 | |
368 | return 0; |
369 | } |
370 | |
371 | |
372 | /* Converts a data string to an LDAP rfc2253 hex string |
373 | * something like '#01020304' |
374 | */ |
375 | int |
376 | _gnutls_x509_data2hex (const opaque * data, size_t data_size, |
377 | opaque * out, size_t * sizeof_out) |
378 | { |
379 | char *res; |
380 | char escaped[MAX_STRING_LEN512]; |
381 | unsigned int size; |
382 | |
383 | if (2 * data_size + 1 > MAX_STRING_LEN512) |
384 | { |
385 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",385); } while(0);; |
386 | return GNUTLS_E_INTERNAL_ERROR-59; |
387 | } |
388 | |
389 | res = _gnutls_bin2hex (data, data_size, escaped, sizeof (escaped), NULL((void*)0)); |
390 | if (!res) |
391 | { |
392 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",392); } while(0);; |
393 | return GNUTLS_E_INTERNAL_ERROR-59; |
394 | } |
395 | |
396 | size = strlen (res) + 1; |
397 | if (size + 1 > *sizeof_out) |
398 | { |
399 | *sizeof_out = size; |
400 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
401 | } |
402 | *sizeof_out = size; /* -1 for the null +1 for the '#' */ |
403 | |
404 | if (out) |
405 | { |
406 | out[0] = '#'; |
407 | out[1] = 0; |
408 | _gnutls_str_cat (out, *sizeof_out, res); |
409 | } |
410 | |
411 | return 0; |
412 | } |
413 | |
414 | |
415 | /* TIME functions |
416 | * Convertions between generalized or UTC time to time_t |
417 | * |
418 | */ |
419 | |
420 | /* This is an emulations of the struct tm. |
421 | * Since we do not use libc's functions, we don't need to |
422 | * depend on the libc structure. |
423 | */ |
424 | typedef struct fake_tm |
425 | { |
426 | int tm_mon; |
427 | int tm_year; /* FULL year - ie 1971 */ |
428 | int tm_mday; |
429 | int tm_hour; |
430 | int tm_min; |
431 | int tm_sec; |
432 | } fake_tm; |
433 | |
434 | /* The mktime_utc function is due to Russ Allbery (rra@stanford.edu), |
435 | * who placed it under public domain: |
436 | */ |
437 | |
438 | /* The number of days in each month. |
439 | */ |
440 | static const int MONTHDAYS[] = { |
441 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 |
442 | }; |
443 | |
444 | /* Whether a given year is a leap year. */ |
445 | #define ISLEAP(year)(((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)) \ |
446 | (((year) % 4) == 0 && (((year) % 100) != 0 || ((year) % 400) == 0)) |
447 | |
448 | /* |
449 | ** Given a struct tm representing a calendar time in UTC, convert it to |
450 | ** seconds since epoch. Returns (time_t) -1 if the time is not |
451 | ** convertable. Note that this function does not canonicalize the provided |
452 | ** struct tm, nor does it allow out of range values or years before 1970. |
453 | */ |
454 | static time_t |
455 | mktime_utc (const struct fake_tm *tm) |
456 | { |
457 | time_t result = 0; |
458 | int i; |
459 | |
460 | /* We do allow some ill-formed dates, but we don't do anything special |
461 | * with them and our callers really shouldn't pass them to us. Do |
462 | * explicitly disallow the ones that would cause invalid array accesses |
463 | * or other algorithm problems. |
464 | */ |
465 | if (tm->tm_mon < 0 || tm->tm_mon > 11 || tm->tm_year < 1970) |
466 | return (time_t) - 1; |
467 | |
468 | /* Convert to a time_t. |
469 | */ |
470 | for (i = 1970; i < tm->tm_year; i++) |
471 | result += 365 + ISLEAP (i)(((i) % 4) == 0 && (((i) % 100) != 0 || ((i) % 400) == 0)); |
472 | for (i = 0; i < tm->tm_mon; i++) |
473 | result += MONTHDAYS[i]; |
474 | if (tm->tm_mon > 1 && ISLEAP (tm->tm_year)(((tm->tm_year) % 4) == 0 && (((tm->tm_year) % 100 ) != 0 || ((tm->tm_year) % 400) == 0))) |
475 | result++; |
476 | result = 24 * (result + tm->tm_mday - 1) + tm->tm_hour; |
477 | result = 60 * result + tm->tm_min; |
478 | result = 60 * result + tm->tm_sec; |
479 | return result; |
480 | } |
481 | |
482 | |
483 | /* this one will parse dates of the form: |
484 | * month|day|hour|minute|sec* (2 chars each) |
485 | * and year is given. Returns a time_t date. |
486 | */ |
487 | static time_t |
488 | _gnutls_x509_time2gtime (const char *ttime, int year) |
489 | { |
490 | char xx[4]; |
491 | struct fake_tm etime; |
492 | time_t ret; |
493 | |
494 | if (strlen (ttime) < 8) |
495 | { |
496 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",496); } while(0);; |
497 | return (time_t) - 1; |
498 | } |
499 | |
500 | etime.tm_year = year; |
501 | |
502 | /* In order to work with 32 bit |
503 | * time_t. |
504 | */ |
505 | if (sizeof (time_t) <= 4 && etime.tm_year >= 2038) |
506 | return (time_t) 2145914603; /* 2037-12-31 23:23:23 */ |
507 | |
508 | if (etime.tm_year < 1970) |
509 | return (time_t) 0; |
510 | |
511 | xx[2] = 0; |
512 | |
513 | /* get the month |
514 | */ |
515 | memcpy (xx, ttime, 2); /* month */ |
516 | etime.tm_mon = atoi (xx) - 1; |
517 | ttime += 2; |
518 | |
519 | /* get the day |
520 | */ |
521 | memcpy (xx, ttime, 2); /* day */ |
522 | etime.tm_mday = atoi (xx); |
523 | ttime += 2; |
524 | |
525 | /* get the hour |
526 | */ |
527 | memcpy (xx, ttime, 2); /* hour */ |
528 | etime.tm_hour = atoi (xx); |
529 | ttime += 2; |
530 | |
531 | /* get the minutes |
532 | */ |
533 | memcpy (xx, ttime, 2); /* minutes */ |
534 | etime.tm_min = atoi (xx); |
535 | ttime += 2; |
536 | |
537 | if (strlen (ttime) >= 2) |
538 | { |
539 | memcpy (xx, ttime, 2); |
540 | etime.tm_sec = atoi (xx); |
541 | ttime += 2; |
542 | } |
543 | else |
544 | etime.tm_sec = 0; |
545 | |
546 | ret = mktime_utc (&etime); |
547 | |
548 | return ret; |
549 | } |
550 | |
551 | |
552 | /* returns a time_t value that contains the given time. |
553 | * The given time is expressed as: |
554 | * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)* |
555 | * |
556 | * (seconds are optional) |
557 | */ |
558 | static time_t |
559 | _gnutls_x509_utcTime2gtime (const char *ttime) |
560 | { |
561 | char xx[3]; |
562 | int year; |
563 | |
564 | if (strlen (ttime) < 10) |
565 | { |
566 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",566); } while(0);; |
567 | return (time_t) - 1; |
568 | } |
569 | xx[2] = 0; |
570 | /* get the year |
571 | */ |
572 | memcpy (xx, ttime, 2); /* year */ |
573 | year = atoi (xx); |
574 | ttime += 2; |
575 | |
576 | if (year > 49) |
577 | year += 1900; |
578 | else |
579 | year += 2000; |
580 | |
581 | return _gnutls_x509_time2gtime (ttime, year); |
582 | } |
583 | |
584 | /* returns a time value that contains the given time. |
585 | * The given time is expressed as: |
586 | * YEAR(2)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2) |
587 | */ |
588 | static int |
589 | _gnutls_x509_gtime2utcTime (time_t gtime, char *str_time, int str_time_size) |
590 | { |
591 | size_t ret; |
592 | struct tm _tm; |
593 | |
594 | if (!gmtime_r (>ime, &_tm)) |
595 | { |
596 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",596); } while(0);; |
597 | return GNUTLS_E_INTERNAL_ERROR-59; |
598 | } |
599 | |
600 | ret = strftime (str_time, str_time_size, "%y%m%d%H%M%SZ", &_tm); |
601 | if (!ret) |
602 | { |
603 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",603); } while(0);; |
604 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
605 | } |
606 | |
607 | |
608 | return 0; |
609 | |
610 | } |
611 | |
612 | /* returns a time_t value that contains the given time. |
613 | * The given time is expressed as: |
614 | * YEAR(4)|MONTH(2)|DAY(2)|HOUR(2)|MIN(2)|SEC(2)* |
615 | */ |
616 | time_t |
617 | _gnutls_x509_generalTime2gtime (const char *ttime) |
618 | { |
619 | char xx[5]; |
620 | int year; |
621 | |
622 | if (strlen (ttime) < 12) |
623 | { |
624 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",624); } while(0);; |
625 | return (time_t) - 1; |
626 | } |
627 | |
628 | if (strchr (ttime, 'Z') == 0) |
629 | { |
630 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",630); } while(0);; |
631 | /* sorry we don't support it yet |
632 | */ |
633 | return (time_t) - 1; |
634 | } |
635 | xx[4] = 0; |
636 | |
637 | /* get the year |
638 | */ |
639 | memcpy (xx, ttime, 4); /* year */ |
640 | year = atoi (xx); |
641 | ttime += 4; |
642 | |
643 | return _gnutls_x509_time2gtime (ttime, year); |
644 | |
645 | } |
646 | |
647 | /* Extracts the time in time_t from the ASN1_TYPE given. When should |
648 | * be something like "tbsCertList.thisUpdate". |
649 | */ |
650 | #define MAX_TIME64 64 |
651 | time_t |
652 | _gnutls_x509_get_time (ASN1_TYPE c2, const char *when) |
653 | { |
654 | char ttime[MAX_TIME64]; |
655 | char name[128]; |
656 | time_t c_time = (time_t) - 1; |
657 | int len, result; |
658 | |
659 | _gnutls_str_cpy (name, sizeof (name), when); |
660 | |
661 | len = sizeof (ttime) - 1; |
662 | if ((result = asn1_read_value (c2, name, ttime, &len)) < 0) |
Although the value stored to 'result' is used in the enclosing expression, the value is never actually read from 'result' | |
663 | { |
664 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",664); } while(0);; |
665 | return (time_t) (-1); |
666 | } |
667 | |
668 | /* CHOICE */ |
669 | if (strcmp (ttime, "generalTime") == 0) |
670 | { |
671 | |
672 | _gnutls_str_cat (name, sizeof (name), ".generalTime"); |
673 | len = sizeof (ttime) - 1; |
674 | result = asn1_read_value (c2, name, ttime, &len); |
675 | if (result == ASN1_SUCCESS0) |
676 | c_time = _gnutls_x509_generalTime2gtime (ttime); |
677 | } |
678 | else |
679 | { /* UTCTIME */ |
680 | |
681 | _gnutls_str_cat (name, sizeof (name), ".utcTime"); |
682 | len = sizeof (ttime) - 1; |
683 | result = asn1_read_value (c2, name, ttime, &len); |
684 | if (result == ASN1_SUCCESS0) |
685 | c_time = _gnutls_x509_utcTime2gtime (ttime); |
686 | } |
687 | |
688 | /* We cannot handle dates after 2031 in 32 bit machines. |
689 | * a time_t of 64bits has to be used. |
690 | */ |
691 | |
692 | if (result != ASN1_SUCCESS0) |
693 | { |
694 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",694); } while(0);; |
695 | return (time_t) (-1); |
696 | } |
697 | return c_time; |
698 | } |
699 | |
700 | /* Sets the time in time_t in the ASN1_TYPE given. Where should |
701 | * be something like "tbsCertList.thisUpdate". |
702 | */ |
703 | int |
704 | _gnutls_x509_set_time (ASN1_TYPE c2, const char *where, time_t tim) |
705 | { |
706 | char str_time[MAX_TIME64]; |
707 | char name[128]; |
708 | int result, len; |
709 | |
710 | _gnutls_str_cpy (name, sizeof (name), where); |
711 | |
712 | if ((result = asn1_write_value (c2, name, "utcTime", 1)) < 0) |
713 | { |
714 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",714); } while(0);; |
715 | return _gnutls_asn2err (result); |
716 | } |
717 | |
718 | result = _gnutls_x509_gtime2utcTime (tim, str_time, sizeof (str_time)); |
719 | if (result < 0) |
720 | { |
721 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",721); } while(0);; |
722 | return result; |
723 | } |
724 | |
725 | _gnutls_str_cat (name, sizeof (name), ".utcTime"); |
726 | |
727 | len = strlen (str_time); |
728 | result = asn1_write_value (c2, name, str_time, len); |
729 | if (result != ASN1_SUCCESS0) |
730 | { |
731 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",731); } while(0);; |
732 | return _gnutls_asn2err (result); |
733 | } |
734 | |
735 | return 0; |
736 | } |
737 | |
738 | |
739 | gnutls_x509_subject_alt_name_t |
740 | _gnutls_x509_san_find_type (char *str_type) |
741 | { |
742 | if (strcmp (str_type, "dNSName") == 0) |
743 | return GNUTLS_SAN_DNSNAME; |
744 | if (strcmp (str_type, "rfc822Name") == 0) |
745 | return GNUTLS_SAN_RFC822NAME; |
746 | if (strcmp (str_type, "uniformResourceIdentifier") == 0) |
747 | return GNUTLS_SAN_URI; |
748 | if (strcmp (str_type, "iPAddress") == 0) |
749 | return GNUTLS_SAN_IPADDRESS; |
750 | if (strcmp (str_type, "otherName") == 0) |
751 | return GNUTLS_SAN_OTHERNAME; |
752 | if (strcmp (str_type, "directoryName") == 0) |
753 | return GNUTLS_SAN_DN; |
754 | return (gnutls_x509_subject_alt_name_t) - 1; |
755 | } |
756 | |
757 | /* A generic export function. Will export the given ASN.1 encoded data |
758 | * to PEM or DER raw data. |
759 | */ |
760 | int |
761 | _gnutls_x509_export_int_named (ASN1_TYPE asn1_data, const char *name, |
762 | gnutls_x509_crt_fmt_t format, |
763 | const char *pem_header, |
764 | unsigned char *output_data, |
765 | size_t * output_data_size) |
766 | { |
767 | int result, len; |
768 | |
769 | if (format == GNUTLS_X509_FMT_DER) |
770 | { |
771 | |
772 | if (output_data == NULL((void*)0)) |
773 | *output_data_size = 0; |
774 | |
775 | len = *output_data_size; |
776 | |
777 | if ((result = |
778 | asn1_der_coding (asn1_data, name, output_data, &len, |
779 | NULL((void*)0))) != ASN1_SUCCESS0) |
780 | { |
781 | *output_data_size = len; |
782 | if (result == ASN1_MEM_ERROR12) |
783 | { |
784 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
785 | } |
786 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",786); } while(0);; |
787 | return _gnutls_asn2err (result); |
788 | } |
789 | |
790 | *output_data_size = len; |
791 | |
792 | } |
793 | else |
794 | { /* PEM */ |
795 | opaque *out; |
796 | gnutls_datum_t tmp; |
797 | |
798 | result = _gnutls_x509_der_encode (asn1_data, name, &tmp, 0); |
799 | if (result < 0) |
800 | { |
801 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",801); } while(0);; |
802 | return result; |
803 | } |
804 | |
805 | result = _gnutls_fbase64_encode (pem_header, tmp.data, tmp.size, &out); |
806 | |
807 | _gnutls_free_datum (&tmp)_gnutls_free_datum_m(&tmp, gnutls_free); |
808 | |
809 | if (result < 0) |
810 | { |
811 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",811); } while(0);; |
812 | return result; |
813 | } |
814 | |
815 | if (result == 0) |
816 | { /* oooops */ |
817 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",817); } while(0);; |
818 | return GNUTLS_E_INTERNAL_ERROR-59; |
819 | } |
820 | |
821 | if ((unsigned) result > *output_data_size) |
822 | { |
823 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",823); } while(0);; |
824 | gnutls_free (out); |
825 | *output_data_size = result; |
826 | return GNUTLS_E_SHORT_MEMORY_BUFFER-51; |
827 | } |
828 | |
829 | *output_data_size = result; |
830 | |
831 | if (output_data) |
832 | { |
833 | memcpy (output_data, out, result); |
834 | |
835 | /* do not include the null character into output size. |
836 | */ |
837 | *output_data_size = result - 1; |
838 | } |
839 | gnutls_free (out); |
840 | |
841 | } |
842 | |
843 | return 0; |
844 | } |
845 | |
846 | int |
847 | _gnutls_x509_export_int (ASN1_TYPE asn1_data, |
848 | gnutls_x509_crt_fmt_t format, |
849 | const char *pem_header, |
850 | unsigned char *output_data, |
851 | size_t * output_data_size) |
852 | { |
853 | return _gnutls_x509_export_int_named (asn1_data, "", |
854 | format, pem_header, output_data, |
855 | output_data_size); |
856 | } |
857 | |
858 | /* Decodes an octet string. Leave string_type null for a normal |
859 | * octet string. Otherwise put something like BMPString, PrintableString |
860 | * etc. |
861 | */ |
862 | int |
863 | _gnutls_x509_decode_octet_string (const char *string_type, |
864 | const opaque * der, size_t der_size, |
865 | opaque * output, size_t * output_size) |
866 | { |
867 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY((void*)0); |
868 | int result, tmp_output_size; |
869 | char strname[64]; |
870 | |
871 | if (string_type == NULL((void*)0)) |
872 | _gnutls_str_cpy (strname, sizeof (strname), "PKIX1.pkcs-7-Data"); |
873 | else |
874 | { |
875 | _gnutls_str_cpy (strname, sizeof (strname), "PKIX1."); |
876 | _gnutls_str_cat (strname, sizeof (strname), string_type); |
877 | } |
878 | |
879 | if ((result = asn1_create_element |
880 | (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), strname, &c2)) != ASN1_SUCCESS0) |
881 | { |
882 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",882); } while(0);; |
883 | result = _gnutls_asn2err (result); |
884 | goto cleanup; |
885 | } |
886 | |
887 | result = asn1_der_decoding (&c2, der, der_size, NULL((void*)0)); |
888 | if (result != ASN1_SUCCESS0) |
889 | { |
890 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",890); } while(0);; |
891 | result = _gnutls_asn2err (result); |
892 | goto cleanup; |
893 | } |
894 | |
895 | tmp_output_size = *output_size; |
896 | result = asn1_read_value (c2, "", output, &tmp_output_size); |
897 | *output_size = tmp_output_size; |
898 | |
899 | if (result != ASN1_SUCCESS0) |
900 | { |
901 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",901); } while(0);; |
902 | result = _gnutls_asn2err (result); |
903 | goto cleanup; |
904 | } |
905 | |
906 | result = 0; |
907 | |
908 | cleanup: |
909 | if (c2) |
910 | asn1_delete_structure (&c2); |
911 | |
912 | return result; |
913 | } |
914 | |
915 | |
916 | /* Reads a value from an ASN1 tree, and puts the output |
917 | * in an allocated variable in the given datum. |
918 | * flags == 0 do nothing with the DER output |
919 | * flags == 1 parse the DER output as OCTET STRING |
920 | * flags == 2 the value is a BIT STRING |
921 | */ |
922 | int |
923 | _gnutls_x509_read_value (ASN1_TYPE c, const char *root, |
924 | gnutls_datum_t * ret, int flags) |
925 | { |
926 | int len = 0, result; |
927 | size_t slen; |
928 | opaque *tmp = NULL((void*)0); |
929 | |
930 | result = asn1_read_value (c, root, NULL((void*)0), &len); |
931 | if (result != ASN1_MEM_ERROR12) |
932 | { |
933 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",933); } while(0);; |
934 | result = _gnutls_asn2err (result); |
935 | return result; |
936 | } |
937 | |
938 | if (flags == 2) |
939 | len /= 8; |
940 | |
941 | tmp = gnutls_malloc (len); |
942 | if (tmp == NULL((void*)0)) |
943 | { |
944 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",944); } while(0);; |
945 | result = GNUTLS_E_MEMORY_ERROR-25; |
946 | goto cleanup; |
947 | } |
948 | |
949 | result = asn1_read_value (c, root, tmp, &len); |
950 | if (result != ASN1_SUCCESS0) |
951 | { |
952 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",952); } while(0);; |
953 | result = _gnutls_asn2err (result); |
954 | goto cleanup; |
955 | } |
956 | |
957 | if (flags == 2) |
958 | len /= 8; |
959 | |
960 | /* Extract the OCTET STRING. |
961 | */ |
962 | |
963 | if (flags == 1) |
964 | { |
965 | slen = len; |
966 | result = _gnutls_x509_decode_octet_string (NULL((void*)0), tmp, slen, tmp, &slen); |
967 | if (result < 0) |
968 | { |
969 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",969); } while(0);; |
970 | goto cleanup; |
971 | } |
972 | len = slen; |
973 | } |
974 | |
975 | ret->data = tmp; |
976 | ret->size = len; |
977 | |
978 | return 0; |
979 | |
980 | cleanup: |
981 | gnutls_free (tmp); |
982 | return result; |
983 | |
984 | } |
985 | |
986 | /* DER Encodes the src ASN1_TYPE and stores it to |
987 | * the given datum. If str is non null then the data are encoded as |
988 | * an OCTET STRING. |
989 | */ |
990 | int |
991 | _gnutls_x509_der_encode (ASN1_TYPE src, const char *src_name, |
992 | gnutls_datum_t * res, int str) |
993 | { |
994 | int size, result; |
995 | int asize; |
996 | opaque *data = NULL((void*)0); |
997 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY((void*)0); |
998 | |
999 | size = 0; |
1000 | result = asn1_der_coding (src, src_name, NULL((void*)0), &size, NULL((void*)0)); |
1001 | if (result != ASN1_MEM_ERROR12) |
1002 | { |
1003 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1003); } while(0);; |
1004 | result = _gnutls_asn2err (result); |
1005 | goto cleanup; |
1006 | } |
1007 | |
1008 | /* allocate data for the der |
1009 | */ |
1010 | |
1011 | if (str) |
1012 | size += 16; /* for later to include the octet tags */ |
1013 | asize = size; |
1014 | |
1015 | data = gnutls_malloc (size); |
1016 | if (data == NULL((void*)0)) |
1017 | { |
1018 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1018); } while(0);; |
1019 | result = GNUTLS_E_MEMORY_ERROR-25; |
1020 | goto cleanup; |
1021 | } |
1022 | |
1023 | result = asn1_der_coding (src, src_name, data, &size, NULL((void*)0)); |
1024 | if (result != ASN1_SUCCESS0) |
1025 | { |
1026 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1026); } while(0);; |
1027 | result = _gnutls_asn2err (result); |
1028 | goto cleanup; |
1029 | } |
1030 | |
1031 | if (str) |
1032 | { |
1033 | if ((result = asn1_create_element |
1034 | (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS0) |
1035 | { |
1036 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1036); } while(0);; |
1037 | result = _gnutls_asn2err (result); |
1038 | goto cleanup; |
1039 | } |
1040 | |
1041 | result = asn1_write_value (c2, "", data, size); |
1042 | if (result != ASN1_SUCCESS0) |
1043 | { |
1044 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1044); } while(0);; |
1045 | result = _gnutls_asn2err (result); |
1046 | goto cleanup; |
1047 | } |
1048 | |
1049 | result = asn1_der_coding (c2, "", data, &asize, NULL((void*)0)); |
1050 | if (result != ASN1_SUCCESS0) |
1051 | { |
1052 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1052); } while(0);; |
1053 | result = _gnutls_asn2err (result); |
1054 | goto cleanup; |
1055 | } |
1056 | |
1057 | size = asize; |
1058 | |
1059 | asn1_delete_structure (&c2); |
1060 | } |
1061 | |
1062 | res->data = data; |
1063 | res->size = size; |
1064 | return 0; |
1065 | |
1066 | cleanup: |
1067 | gnutls_free (data); |
1068 | asn1_delete_structure (&c2); |
1069 | return result; |
1070 | |
1071 | } |
1072 | |
1073 | /* DER Encodes the src ASN1_TYPE and stores it to |
1074 | * dest in dest_name. Useful to encode something and store it |
1075 | * as OCTET. If str is non null then the data are encoded as |
1076 | * an OCTET STRING. |
1077 | */ |
1078 | int |
1079 | _gnutls_x509_der_encode_and_copy (ASN1_TYPE src, const char *src_name, |
1080 | ASN1_TYPE dest, const char *dest_name, |
1081 | int str) |
1082 | { |
1083 | int result; |
1084 | gnutls_datum_t encoded; |
1085 | |
1086 | result = _gnutls_x509_der_encode (src, src_name, &encoded, str); |
1087 | |
1088 | if (result < 0) |
1089 | { |
1090 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1090); } while(0);; |
1091 | return result; |
1092 | } |
1093 | |
1094 | /* Write the data. |
1095 | */ |
1096 | result = asn1_write_value (dest, dest_name, encoded.data, encoded.size); |
1097 | |
1098 | _gnutls_free_datum (&encoded)_gnutls_free_datum_m(&encoded, gnutls_free); |
1099 | |
1100 | if (result != ASN1_SUCCESS0) |
1101 | { |
1102 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1102); } while(0);; |
1103 | return _gnutls_asn2err (result); |
1104 | } |
1105 | |
1106 | return 0; |
1107 | } |
1108 | |
1109 | /* Writes the value of the datum in the given ASN1_TYPE. If str is non |
1110 | * (0) it encodes it as OCTET STRING. |
1111 | */ |
1112 | int |
1113 | _gnutls_x509_write_value (ASN1_TYPE c, const char *root, |
1114 | const gnutls_datum_t * data, int str) |
1115 | { |
1116 | int result; |
1117 | ASN1_TYPE c2 = ASN1_TYPE_EMPTY((void*)0); |
1118 | gnutls_datum_t val = { NULL((void*)0), 0 }; |
1119 | |
1120 | if (str) |
1121 | { |
1122 | /* Convert it to OCTET STRING |
1123 | */ |
1124 | if ((result = asn1_create_element |
1125 | (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), "PKIX1.pkcs-7-Data", &c2)) != ASN1_SUCCESS0) |
1126 | { |
1127 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1127); } while(0);; |
1128 | result = _gnutls_asn2err (result); |
1129 | goto cleanup; |
1130 | } |
1131 | |
1132 | result = asn1_write_value (c2, "", data->data, data->size); |
1133 | if (result != ASN1_SUCCESS0) |
1134 | { |
1135 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1135); } while(0);; |
1136 | result = _gnutls_asn2err (result); |
1137 | goto cleanup; |
1138 | } |
1139 | |
1140 | result = _gnutls_x509_der_encode (c2, "", &val, 0); |
1141 | if (result < 0) |
1142 | { |
1143 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1143); } while(0);; |
1144 | goto cleanup; |
1145 | } |
1146 | |
1147 | } |
1148 | else |
1149 | { |
1150 | val.data = data->data; |
1151 | val.size = data->size; |
1152 | } |
1153 | |
1154 | /* Write the data. |
1155 | */ |
1156 | result = asn1_write_value (c, root, val.data, val.size); |
1157 | if (result != ASN1_SUCCESS0) |
1158 | { |
1159 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1159); } while(0);; |
1160 | result = _gnutls_asn2err (result); |
1161 | goto cleanup; |
1162 | } |
1163 | |
1164 | result = 0; |
1165 | |
1166 | cleanup: |
1167 | asn1_delete_structure (&c2); |
1168 | if (val.data != data->data) |
1169 | _gnutls_free_datum (&val)_gnutls_free_datum_m(&val, gnutls_free); |
1170 | return result; |
1171 | } |
1172 | |
1173 | void |
1174 | _asnstr_append_name (char *name, size_t name_size, const char *part1, |
1175 | const char *part2) |
1176 | { |
1177 | if (part1[0] != 0) |
1178 | { |
1179 | _gnutls_str_cpy (name, name_size, part1); |
1180 | _gnutls_str_cat (name, name_size, part2); |
1181 | } |
1182 | else |
1183 | _gnutls_str_cpy (name, name_size, part2 + 1 /* remove initial dot */ ); |
1184 | } |
1185 | |
1186 | |
1187 | |
1188 | /* Encodes and copies the private key parameters into a |
1189 | * subjectPublicKeyInfo structure. |
1190 | * |
1191 | */ |
1192 | int |
1193 | _gnutls_x509_encode_and_copy_PKI_params (ASN1_TYPE dst, |
1194 | const char *dst_name, |
1195 | gnutls_pk_algorithm_t |
1196 | pk_algorithm, gnutls_pk_params_st * params) |
1197 | { |
1198 | const char *pk; |
1199 | gnutls_datum_t der = { NULL((void*)0), 0 }; |
1200 | int result; |
1201 | char name[128]; |
1202 | |
1203 | pk = _gnutls_x509_pk_to_oid (pk_algorithm); |
1204 | if (pk == NULL((void*)0)) |
1205 | { |
1206 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1206); } while(0);; |
1207 | return GNUTLS_E_UNKNOWN_PK_ALGORITHM-80; |
1208 | } |
1209 | |
1210 | /* write the OID |
1211 | */ |
1212 | _asnstr_append_name (name, sizeof (name), dst_name, ".algorithm.algorithm"); |
1213 | |
1214 | result = asn1_write_value (dst, name, pk, 1); |
1215 | if (result != ASN1_SUCCESS0) |
1216 | { |
1217 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1217); } while(0);; |
1218 | return _gnutls_asn2err (result); |
1219 | } |
1220 | |
1221 | result = _gnutls_x509_write_pubkey_params (pk_algorithm, params, &der); |
1222 | if (result < 0) |
1223 | { |
1224 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1224); } while(0);; |
1225 | return result; |
1226 | } |
1227 | |
1228 | _asnstr_append_name (name, sizeof (name), dst_name, |
1229 | ".algorithm.parameters"); |
1230 | |
1231 | result = asn1_write_value (dst, name, der.data, der.size); |
1232 | |
1233 | _gnutls_free_datum (&der)_gnutls_free_datum_m(&der, gnutls_free); |
1234 | |
1235 | if (result != ASN1_SUCCESS0) |
1236 | { |
1237 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1237); } while(0);; |
1238 | return _gnutls_asn2err (result); |
1239 | } |
1240 | |
1241 | result = _gnutls_x509_write_pubkey (pk_algorithm, params, &der); |
1242 | if (result < 0) |
1243 | { |
1244 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1244); } while(0);; |
1245 | return result; |
1246 | } |
1247 | |
1248 | /* Write the DER parameters. (in bits) |
1249 | */ |
1250 | _asnstr_append_name (name, sizeof (name), dst_name, |
1251 | ".subjectPublicKey"); |
1252 | result = asn1_write_value (dst, name, der.data, der.size * 8); |
1253 | _gnutls_free_datum (&der)_gnutls_free_datum_m(&der, gnutls_free); |
1254 | |
1255 | if (result != ASN1_SUCCESS0) |
1256 | { |
1257 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1257); } while(0);; |
1258 | return _gnutls_asn2err (result); |
1259 | } |
1260 | |
1261 | return 0; |
1262 | } |
1263 | |
1264 | /* Encodes and public key parameters into a |
1265 | * subjectPublicKeyInfo structure and stores it in der. |
1266 | */ |
1267 | int |
1268 | _gnutls_x509_encode_PKI_params (gnutls_datum_t *der, |
1269 | gnutls_pk_algorithm_t |
1270 | pk_algorithm, gnutls_pk_params_st * params) |
1271 | { |
1272 | int ret; |
1273 | ASN1_TYPE tmp; |
1274 | |
1275 | ret = asn1_create_element (_gnutls_get_pkix ()((ASN1_TYPE) _gnutls_pkix1_asn), |
1276 | "PKIX1.Certificate", &tmp); |
1277 | if (ret != ASN1_SUCCESS0) |
1278 | { |
1279 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1279); } while(0);; |
1280 | return _gnutls_asn2err (ret); |
1281 | } |
1282 | |
1283 | ret = _gnutls_x509_encode_and_copy_PKI_params (tmp, |
1284 | "tbsCertificate.subjectPublicKeyInfo", |
1285 | pk_algorithm, params); |
1286 | if (ret != ASN1_SUCCESS0) |
1287 | { |
1288 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1288); } while(0);; |
1289 | ret = _gnutls_asn2err (ret); |
1290 | goto cleanup; |
1291 | } |
1292 | |
1293 | ret = _gnutls_x509_der_encode(tmp, "tbsCertificate.subjectPublicKeyInfo", der, 0); |
1294 | |
1295 | cleanup: |
1296 | asn1_delete_structure (&tmp); |
1297 | |
1298 | return ret; |
1299 | } |
1300 | |
1301 | /* Reads and returns the PK algorithm of the given certificate-like |
1302 | * ASN.1 structure. src_name should be something like "tbsCertificate.subjectPublicKeyInfo". |
1303 | */ |
1304 | int |
1305 | _gnutls_x509_get_pk_algorithm (ASN1_TYPE src, const char *src_name, |
1306 | unsigned int *bits) |
1307 | { |
1308 | int result; |
1309 | int algo; |
1310 | char oid[64]; |
1311 | int len; |
1312 | gnutls_pk_params_st params; |
1313 | char name[128]; |
1314 | |
1315 | gnutls_pk_params_init(¶ms); |
1316 | |
1317 | _asnstr_append_name (name, sizeof (name), src_name, ".algorithm.algorithm"); |
1318 | len = sizeof (oid); |
1319 | result = asn1_read_value (src, name, oid, &len); |
1320 | |
1321 | if (result != ASN1_SUCCESS0) |
1322 | { |
1323 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1323); } while(0);; |
1324 | return _gnutls_asn2err (result); |
1325 | } |
1326 | |
1327 | algo = _gnutls_x509_oid2pk_algorithm (oid); |
1328 | if (algo == GNUTLS_PK_UNKNOWN) |
1329 | { |
1330 | _gnutls_debug_logdo { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "%s: unknown public key algorithm: %s\n", __func__, oid) ; } while(0) |
1331 | ("%s: unknown public key algorithm: %s\n", __func__, oid)do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "%s: unknown public key algorithm: %s\n", __func__, oid) ; } while(0); |
1332 | } |
1333 | |
1334 | if (bits == NULL((void*)0)) |
1335 | { |
1336 | return algo; |
1337 | } |
1338 | |
1339 | /* Now read the parameters' bits |
1340 | */ |
1341 | result = _gnutls_get_asn_mpis(src, src_name, ¶ms); |
1342 | if (result < 0) |
1343 | return gnutls_assert_val(result)gnutls_assert_val_int(result, "common.c", 1343); |
1344 | |
1345 | bits[0] = pubkey_to_bits(algo, ¶ms); |
1346 | |
1347 | gnutls_pk_params_release(¶ms); |
1348 | return algo; |
1349 | } |
1350 | |
1351 | /* Reads the DER signed data from the certificate and allocates space and |
1352 | * returns them into signed_data. |
1353 | */ |
1354 | int |
1355 | _gnutls_x509_get_signed_data (ASN1_TYPE src, const char *src_name, |
1356 | gnutls_datum_t * signed_data) |
1357 | { |
1358 | gnutls_datum_t der; |
1359 | int start, end, result; |
1360 | |
1361 | result = _gnutls_x509_der_encode (src, "", &der, 0); |
1362 | if (result < 0) |
1363 | { |
1364 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1364); } while(0);; |
1365 | return result; |
1366 | } |
1367 | |
1368 | /* Get the signed data |
1369 | */ |
1370 | result = asn1_der_decoding_startEnd (src, der.data, der.size, |
1371 | src_name, &start, &end); |
1372 | if (result != ASN1_SUCCESS0) |
1373 | { |
1374 | result = _gnutls_asn2err (result); |
1375 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1375); } while(0);; |
1376 | goto cleanup; |
1377 | } |
1378 | |
1379 | result = _gnutls_set_datum (signed_data, &der.data[start], end - start + 1)_gnutls_set_datum_m(signed_data,&der.data[start],end - start + 1, gnutls_malloc); |
1380 | |
1381 | if (result < 0) |
1382 | { |
1383 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1383); } while(0);; |
1384 | goto cleanup; |
1385 | } |
1386 | |
1387 | result = 0; |
1388 | |
1389 | cleanup: |
1390 | _gnutls_free_datum (&der)_gnutls_free_datum_m(&der, gnutls_free); |
1391 | |
1392 | return result; |
1393 | } |
1394 | |
1395 | /*- |
1396 | * gnutls_x509_get_signature_algorithm: |
1397 | * @src: should contain an ASN1_TYPE structure |
1398 | * @src_name: the description of the signature field |
1399 | * |
1400 | * This function will return a value of the #gnutls_sign_algorithm_t |
1401 | * enumeration that is the signature algorithm that has been used to |
1402 | * sign this certificate. |
1403 | * |
1404 | * Returns: a #gnutls_sign_algorithm_t value, or a negative error code on |
1405 | * error. |
1406 | -*/ |
1407 | int |
1408 | _gnutls_x509_get_signature_algorithm (ASN1_TYPE src, const char *src_name) |
1409 | { |
1410 | int result; |
1411 | gnutls_datum_t sa; |
1412 | |
1413 | /* Read the signature algorithm. Note that parameters are not |
1414 | * read. They will be read from the issuer's certificate if needed. |
1415 | */ |
1416 | result = |
1417 | _gnutls_x509_read_value (src, src_name, &sa, 0); |
1418 | |
1419 | if (result < 0) |
1420 | { |
1421 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1421); } while(0);; |
1422 | return result; |
1423 | } |
1424 | |
1425 | result = _gnutls_x509_oid2sign_algorithm (sa.data); |
1426 | |
1427 | _gnutls_free_datum (&sa)_gnutls_free_datum_m(&sa, gnutls_free); |
1428 | |
1429 | return result; |
1430 | } |
1431 | |
1432 | |
1433 | /* Reads the DER signature from the certificate and allocates space and |
1434 | * returns them into signed_data. |
1435 | */ |
1436 | int |
1437 | _gnutls_x509_get_signature (ASN1_TYPE src, const char *src_name, |
1438 | gnutls_datum_t * signature) |
1439 | { |
1440 | int bits, result, len; |
1441 | |
1442 | signature->data = NULL((void*)0); |
1443 | signature->size = 0; |
1444 | |
1445 | /* Read the signature |
1446 | */ |
1447 | bits = 0; |
1448 | result = asn1_read_value (src, src_name, NULL((void*)0), &bits); |
1449 | |
1450 | if (result != ASN1_MEM_ERROR12) |
1451 | { |
1452 | result = _gnutls_asn2err (result); |
1453 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1453); } while(0);; |
1454 | goto cleanup; |
1455 | } |
1456 | |
1457 | if (bits % 8 != 0) |
1458 | { |
1459 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1459); } while(0);; |
1460 | result = GNUTLS_E_CERTIFICATE_ERROR-43; |
1461 | goto cleanup; |
1462 | } |
1463 | |
1464 | len = bits / 8; |
1465 | |
1466 | signature->data = gnutls_malloc (len); |
1467 | if (signature->data == NULL((void*)0)) |
1468 | { |
1469 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1469); } while(0);; |
1470 | result = GNUTLS_E_MEMORY_ERROR-25; |
1471 | return result; |
1472 | } |
1473 | |
1474 | /* read the bit string of the signature |
1475 | */ |
1476 | bits = len; |
1477 | result = asn1_read_value (src, src_name, signature->data, &bits); |
1478 | |
1479 | if (result != ASN1_SUCCESS0) |
1480 | { |
1481 | result = _gnutls_asn2err (result); |
1482 | gnutls_assert ()do { if (__builtin_expect((_gnutls_log_level >= 2), 0)) _gnutls_log ( 2, "ASSERT: %s:%d\n", "common.c",1482); } while(0);; |
1483 | goto cleanup; |
1484 | } |
1485 | |
1486 | signature->size = len; |
1487 | |
1488 | return 0; |
1489 | |
1490 | cleanup: |
1491 | return result; |
1492 | } |