]> git.saurik.com Git - apple/security.git/blob - AppleX509CL/CertFields.cpp
Security-29.tar.gz
[apple/security.git] / AppleX509CL / CertFields.cpp
1 /*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19 /*
20 * CertFields.cpp - convert between snacc-based Certificate components and CDSA-style
21 * fields. A major component of DecodedCert.
22 *
23 * Created 9/1/2000 by Doug Mitchell.
24 * Copyright (c) 2000 by Apple Computer.
25 *
26 * The code in this file is dreadfully gross. There is no practical way to do this
27 * work (converting between C++ snacc types and C CSDA types) without the kind
28 * of brute force code you see here.
29 */
30
31 #include "DecodedCert.h"
32 #include "cldebugging.h"
33 #include "CertBuilder.h"
34 #include "CLCertExtensions.h"
35 #include "SnaccUtils.h"
36 #include <Security/utilities.h>
37 #include <Security/oidscert.h>
38 #include <Security/cssmerr.h>
39 #include <Security/x509defs.h>
40 #include <Security/cdsaUtils.h>
41
42 /*
43 * Routines for common validity checking for certificateToSign fields.
44 *
45 * Call from setField*: verify field isn't already set, optionally validate
46 * input length
47 */
48 static void tbsSetCheck(
49 void *fieldToSet,
50 const CssmData &fieldValue,
51 uint32 expLength,
52 const char *op)
53 {
54 if(fieldToSet != NULL) {
55 /* can't add another */
56 errorLog1("setField(%s): field already set\n", op);
57 CssmError::throwMe(CSSMERR_CL_INVALID_NUMBER_OF_FIELDS);
58 }
59 if((expLength != 0) && (fieldValue.length() != expLength)) {
60 errorLog3("setField(%s): bad length : exp %d got %d\n",
61 op, (int)expLength, (int)fieldValue.length());
62 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
63 }
64 }
65
66 /*
67 * Call from getField* for unique fields - detect missing field or index out of bounds.
68 */
69 static bool tbsGetCheck(
70 void *requiredField,
71 uint32 reqIndex)
72 {
73 if((requiredField == NULL) || (reqIndex != 0)) {
74 return false;
75 }
76 else {
77 return true;
78 }
79 }
80
81 /***
82 *** Version
83 *** Format = DER-encoded int (max of four bytes in this case)
84 ***/
85 static bool getField_Version (
86 const DecodedCert &cert,
87 unsigned index, // which occurrence (0 = first)
88 uint32 &numFields, // RETURNED
89 CssmOwnedData &fieldValue) // RETURNED
90 {
91 if(!tbsGetCheck(cert.certificateToSign->version, index)) {
92 return false;
93 }
94
95 /* cook up big-endian char array representation */
96 int ivers = *cert.certificateToSign->version;
97 uint32 uvers = static_cast<uint32>(ivers);
98 uint8 chars[sizeof(uint32)];
99 for(uint32 i=0; i<sizeof(uint32); i++) {
100 chars[sizeof(uint32) - 1 -i] = (uint8)uvers;
101 uvers >>= 8;
102 }
103 fieldValue.copy(chars, sizeof(uint32));
104 numFields = 1;
105 return true;
106 }
107
108 static void setField_Version (
109 DecodedCert &cert,
110 const CssmData &fieldValue)
111 {
112 tbsSetCheck(cert.certificateToSign->version, fieldValue, 0, "version");
113
114 /* get big-endian int from *fieldValue.Data */
115 if(fieldValue.length() > sizeof(unsigned)) {
116 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
117 }
118 uint32 vers = 0;
119 uint8 *cp = fieldValue;
120 for(unsigned i=0; i<fieldValue.length(); i++) {
121 vers <<= 8;
122 vers |= cp[i];
123 }
124 cert.certificateToSign->version = new Version((int)vers);
125 cert.certificateToSign->version->Set((int)vers);
126 }
127
128
129 #if this_is_a_template
130 /***
131 *** Version
132 *** Format = DER-encoded int (always four bytes in this case)
133 ***/
134 static bool getField_Version (
135 const DecodedCert &cert,
136 unsigned index, // which occurrence (0 = first)
137 uint32 &numFields, // RETURNED
138 CssmOwnedData &fieldValue) // RETURNED
139 {
140 tbsGetCheck(cert.certificateToSign->version, index);
141 }
142 static void setField_Version (
143 DecodedCert &cert,
144 const CssmData &fieldValue)
145 {
146 tbsSetCheck(cert.certificateToSign->version, fieldValue, sizeof(uint32),
147 "version");
148
149 }
150 static void freeField_Version (
151 CssmOwnedData &fieldValue)
152 {
153 }
154 #endif
155
156 /***
157 *** Serial Number
158 *** Format = DER-encoded int, variable length
159 ***/
160 static bool getField_SerialNumber (
161 const DecodedCert &cert,
162 unsigned index, // which occurrence (0 = first)
163 uint32 &numFields, // RETURNED
164 CssmOwnedData &fieldValue) // RETURNED
165 {
166 if(index > 0) {
167 return false;
168 }
169
170 char *cp = cert.certificateToSign->serialNumber;
171 uint32 len = cert.certificateToSign->serialNumber.Len();
172 fieldValue.copy(cp, len);
173 numFields = 1;
174 return true;
175 }
176
177 static void setField_SerialNumber (
178 DecodedCert &cert,
179 const CssmData &fieldValue)
180 {
181 cert.certificateToSign->serialNumber.Set(fieldValue, fieldValue.Length);
182 }
183
184 /***
185 *** Issuer Name, Subject Name (C struct version)
186 *** Format = CSSM_X509_NAME
187 *** class Name from sm_x501if
188 ***/
189
190 /* first, the common code */
191 static bool getField_RDN (
192 const Name &name,
193 uint32 &numFields, // RETURNED (if successful, 0 or 1)
194 CssmOwnedData &fieldValue) // RETURNED
195 {
196 RDNSequence *rdns = name.rDNSequence;
197 int numRdns = rdns->Count();
198 if((rdns == NULL) || (numRdns == 0)) {
199 /* not technically an error */
200 return false;
201 }
202
203 /* alloc top-level CSSM_X509_NAME and its RelativeDistinguishedName array */
204 CssmAllocator &alloc = fieldValue.allocator;
205 fieldValue.malloc(sizeof(CSSM_X509_NAME));
206 CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data();
207 memset(x509Name, 0, sizeof(CSSM_X509_NAME));
208 x509Name->numberOfRDNs = numRdns;
209 x509Name->RelativeDistinguishedName =
210 (CSSM_X509_RDN_PTR)alloc.malloc(sizeof(CSSM_X509_RDN) * numRdns);
211 CSSM_X509_RDN_PTR currRdn = x509Name->RelativeDistinguishedName;
212 memset(currRdn, 0, sizeof(CSSM_X509_RDN) * numRdns);
213
214 rdns->SetCurrElmt(0);
215 for(int rdnDex=0; rdnDex<numRdns; rdnDex++) {
216 /* from sm_x501if */
217 RelativeDistinguishedName *rdn = rdns->Curr();
218 if(rdn == NULL) {
219 /* not sure how this can happen... */
220 dprintf1("getField_RDN: NULL rdn at index %d\n", rdnDex);
221
222 /* next snacc RDN but keep CDSA position unchanged */
223 rdns->GoNext(); // snacc format
224 x509Name->numberOfRDNs--; // since we're skipping one
225 continue;
226 }
227 int numAttrs = rdn->Count();
228 if(numAttrs == 0) {
229 dprintf1("getField_RDN: zero numAttrs at index %d\n", rdnDex);
230 rdns->GoNext();
231 x509Name->numberOfRDNs--; // since we're skipping one
232 continue;
233 }
234
235 /* alloc CSSM_X509_TYPE_VALUE_PAIR array for this rdn */
236 currRdn->numberOfPairs = numAttrs;
237 currRdn->AttributeTypeAndValue = (CSSM_X509_TYPE_VALUE_PAIR_PTR)
238 alloc.malloc(sizeof(CSSM_X509_TYPE_VALUE_PAIR) * numAttrs);
239 CSSM_X509_TYPE_VALUE_PAIR_PTR currAttr = currRdn->AttributeTypeAndValue;
240 memset(currAttr, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR) * numAttrs);
241
242 /* descend into array of attribute/values */
243 rdn->SetCurrElmt(0);
244 for(int attrDex=0; attrDex<numAttrs; attrDex++) {
245 /* from sm_x501if */
246 AttributeTypeAndDistinguishedValue *att = rdn->Curr();
247 if(att == NULL) {
248 /* not sure how this can happen... */
249 dprintf1("getField_RDN: NULL att at index %d\n", attrDex);
250 rdn->GoNext();
251 currRdn->numberOfPairs--;
252 continue;
253 }
254
255 /*
256 * Convert snacc-style AttributeTypeAndDistinguishedValue to
257 * CSSM-style CSSM_X509_TYPE_VALUE_PAIR
258 *
259 * Hopefully 'value' is one of the types defined in DirectoryString,
260 * defined in sm_x520sa. Some certs use IA5String, which is not
261 * technically legal and is not handled by DirectoryString, so
262 * we have to handle that ourself. See e.g. the Thawte serverbasic
263 * cert, which has an email address in IA5String format.
264 */
265 CSM_Buffer *cbuf = att->value.value;
266 AsnBuf buf;
267 AsnLen len = cbuf->Length();
268 AsnTag tag;
269 AsnLen elmtLen;
270 ENV_TYPE env;
271 int val;
272 char *valData;
273 int valLength;
274 DirectoryString *dirStr = NULL;
275
276 buf.InstallData(cbuf->Access(), len);
277 if ((val = setjmp (env)) == 0) {
278 tag = BDecTag (buf, len, env);
279 elmtLen = BDecLen (buf, len, env);
280 }
281 else {
282 errorLog0("getField_RDN: malformed DirectoryString (1)\n");
283 /* FIXME - throw? Discard the whole cert? What? */
284 rdn->GoNext();
285 currRdn->numberOfPairs--;
286 continue;
287 }
288
289 /* current buf ptr is at the string value's contents. */
290 if((tag == MAKE_TAG_ID (UNIV, PRIM, IA5STRING_TAG_CODE)) ||
291 (tag == MAKE_TAG_ID (UNIV, CONS, IA5STRING_TAG_CODE))) {
292 /* any other printable types not handled by DirectoryString here */
293 valData = buf.DataPtr();
294 valLength = buf.DataLen();
295 // workaround
296 delete dirStr;
297 dirStr = NULL;
298 }
299 else {
300 /* from sm_x520sa.h */
301 AsnLen dec;
302 dirStr = new DirectoryString;
303 if((val = setjmp (env)) == 0) {
304 dirStr->BDecContent(buf, tag, elmtLen, dec, env);
305 }
306 else {
307 errorLog0("getField_RDN: malformed DirectoryString (1)\n");
308 /* FIXME - throw? Discard the whole cert? What? */
309 rdn->GoNext();
310 currRdn->numberOfPairs--;
311 continue;
312 }
313 AsnOcts *octs = NULL;
314 switch(dirStr->choiceId) {
315 case DirectoryString::printableStringCid:
316 octs = dirStr->printableString;
317 break;
318 case DirectoryString::teletexStringCid:
319 octs = dirStr->teletexString;
320 break;
321 case DirectoryString::universalStringCid:
322 octs = dirStr->universalString;
323 break;
324 case DirectoryString::bmpStringCid:
325 octs = dirStr->bmpString;
326 break;
327 case DirectoryString::utf8StringCid:
328 octs = dirStr->utf8String;
329 break;
330 default:
331 /* should never happen unless DirectoryString changes */
332 errorLog1("getField_RDN: Bad DirectoryString::choiceId (%d)\n",
333 (int)dirStr->choiceId);
334 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
335 }
336 valData = *octs;
337 valLength = octs->Len();
338 } /* normal DirectoryString */
339
340 /* OK, set up outgoing CSSM_X509_TYPE_VALUE_PAIR */
341 CssmOid &oid = CssmOid::overlay(currAttr->type);
342 CL_snaccOidToCssm(att->type, oid, alloc);
343 currAttr->valueType = tag >> 24;
344 currAttr->value.Data = (uint8 *)alloc.malloc(valLength);
345 currAttr->value.Length = valLength;
346 memcpy(currAttr->value.Data, valData, valLength);
347
348 rdn->GoNext(); // snacc format
349 currAttr++; // CDSA format
350 delete dirStr;
351 } /* for eact attr in rdn */
352
353 rdns->GoNext(); // snacc format
354 currRdn++; // CDSA format
355 } /* for each rdn in rdns */
356 numFields = 1;
357 return true;
358 }
359
360 static void setField_RDN (
361 NameBuilder &name,
362 const CssmData &fieldValue)
363 {
364 /*
365 * The main job here is extracting attr/value pairs in CSSM format
366 * from fieldData, and converting them into arguments for NameBuilder.addATDV.
367 * Note that we're taking the default for primaryDistinguished,
368 * because the CDSA CSSM_X509_TYPE_VALUE_PAIR struct doesn't allow for
369 * it.
370 */
371 CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data();
372 for(unsigned rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) {
373 CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex];
374 if(rdn->numberOfPairs != 1) {
375 errorLog0("setField_RDN: only one a/v pair per RDN supported\n");
376 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
377 }
378
379 CSSM_X509_TYPE_VALUE_PAIR_PTR atv = rdn->AttributeTypeAndValue;
380 AsnOid oid;
381 oid.Set(reinterpret_cast<char *>(atv->type.Data), atv->type.Length);
382
383 DirectoryString::ChoiceIdEnum stringType;
384 switch(atv->valueType) {
385 case BER_TAG_T61_STRING:
386 stringType = DirectoryString::teletexStringCid;
387 break;
388 case BER_TAG_PRINTABLE_STRING:
389 stringType = DirectoryString::printableStringCid;
390 break;
391 case BER_TAG_PKIX_UNIVERSAL_STRING:
392 stringType = DirectoryString::universalStringCid;
393 break;
394 case BER_TAG_PKIX_BMP_STRING:
395 stringType = DirectoryString::bmpStringCid;
396 break;
397 case BER_TAG_PKIX_UTF8_STRING:
398 stringType = DirectoryString::utf8StringCid;
399 break;
400 default:
401 errorLog1("setField_RDN: illegal tag(%d)\n", atv->valueType);
402 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
403 }
404 name.addATDV(oid,
405 reinterpret_cast<char *>(atv->value.Data),
406 atv->value.Length,
407 stringType);
408
409 }
410 }
411
412 /* common for issuer and subject */
413 static void freeField_RDN (
414 CssmOwnedData &fieldValue)
415 {
416 if(fieldValue.data() == NULL) {
417 return;
418 }
419 if(fieldValue.length() != sizeof(CSSM_X509_NAME)) {
420 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
421 }
422 CssmAllocator &alloc = fieldValue.allocator;
423 CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data();
424 for(unsigned rdnDex=0; rdnDex<x509Name->numberOfRDNs; rdnDex++) {
425 CSSM_X509_RDN_PTR rdn = &x509Name->RelativeDistinguishedName[rdnDex];
426 for(unsigned atvDex=0; atvDex<rdn->numberOfPairs; atvDex++) {
427 CSSM_X509_TYPE_VALUE_PAIR_PTR atv = &rdn->AttributeTypeAndValue[atvDex];
428 alloc.free(atv->type.Data);
429 alloc.free(atv->value.Data);
430 memset(atv, 0, sizeof(CSSM_X509_TYPE_VALUE_PAIR));
431 }
432 alloc.free(rdn->AttributeTypeAndValue);
433 memset(rdn, 0, sizeof(CSSM_X509_RDN));
434 }
435 alloc.free(x509Name->RelativeDistinguishedName);
436 memset(x509Name, 0, sizeof(CSSM_X509_NAME));
437
438 /* top-level x509Name pointer freed by freeCertFieldData() */
439 }
440
441 /*** issuer ***/
442 static bool getField_Issuer (
443 const DecodedCert &cert,
444 unsigned index, // which occurrence (0 = first)
445 uint32 &numFields, // RETURNED
446 CssmOwnedData &fieldValue) // RETURNED
447 {
448 bool brtn;
449
450 if(!tbsGetCheck(cert.certificateToSign->issuer, index)) {
451 return false;
452 }
453 try {
454 brtn = getField_RDN(*cert.certificateToSign->issuer, numFields, fieldValue);
455 }
456 catch (...) {
457 freeField_RDN(fieldValue);
458 throw;
459 }
460 return brtn;
461 }
462
463 static void setField_Issuer (
464 DecodedCert &cert,
465 const CssmData &fieldValue)
466 {
467 tbsSetCheck(cert.certificateToSign->issuer, fieldValue, sizeof(CSSM_X509_NAME),
468 "IssuerName");
469 NameBuilder *issuer = new NameBuilder;
470 cert.certificateToSign->issuer = issuer;
471 setField_RDN(*issuer, fieldValue);
472 }
473
474 /*** subject ***/
475 static bool getField_Subject (
476 const DecodedCert &cert,
477 unsigned index, // which occurrence (0 = first)
478 uint32 &numFields, // RETURNED
479 CssmOwnedData &fieldValue) // RETURNED
480 {
481 if(!tbsGetCheck(cert.certificateToSign->subject, index)) {
482 return false;
483 }
484 bool brtn;
485 try {
486 brtn = getField_RDN(*cert.certificateToSign->subject, numFields, fieldValue);
487 }
488 catch (...) {
489 freeField_RDN(fieldValue);
490 throw;
491 }
492 return brtn;
493 }
494
495 static void setField_Subject (
496 DecodedCert &cert,
497 const CssmData &fieldValue)
498 {
499 tbsSetCheck(cert.certificateToSign->subject, fieldValue, sizeof(CSSM_X509_NAME),
500 "SubjectName");
501 NameBuilder *subject = new NameBuilder;
502 cert.certificateToSign->subject = subject;
503 setField_RDN(*subject, fieldValue);
504 }
505
506 /***
507 *** Issuer Name, Subject Name (normalized and encoded version)
508 *** Format = CSSM_DATA containing the DER encoding of the normalized name
509 *** class Name from sm_x501if
510 ***/
511
512 /* first, the common code */
513 static bool getField_normRDN (
514 const Name &name,
515 uint32 &numFields, // RETURNED (if successful, 0 or 1)
516 CssmOwnedData &fieldValue) // RETURNED
517 {
518 /*
519 * First step is to make a copy of the existing name. The easiest way to do
520 * this is to encode and decode.
521 */
522 CssmAllocator &alloc = fieldValue.allocator;
523 CssmAutoData encodedName1(alloc);
524 /* FIXME - should SC_encodeAsnObj() take a const AsnType & ? */
525 SC_encodeAsnObj(const_cast<Name &>(name), encodedName1, MAX_RDN_SIZE);
526 Name decodedName;
527 SC_decodeAsnObj(encodedName1, decodedName);
528
529 /* normalize */
530 CL_normalizeX509Name(decodedName, alloc);
531
532 /* encode result */
533 SC_encodeAsnObj(decodedName, fieldValue, MAX_RDN_SIZE);
534 numFields = 1;
535 return true;
536 }
537
538 static bool getFieldSubjectNorm(
539 const DecodedCert &cert,
540 unsigned index, // which occurrence (0 = first)
541 uint32 &numFields, // RETURNED
542 CssmOwnedData &fieldValue) // RETURNED
543 {
544 if(!tbsGetCheck(cert.certificateToSign->subject, index)) {
545 return false;
546 }
547 return getField_normRDN(*cert.certificateToSign->subject, numFields, fieldValue);
548 }
549
550 static bool getFieldIssuerNorm(
551 const DecodedCert &cert,
552 unsigned index, // which occurrence (0 = first)
553 uint32 &numFields, // RETURNED
554 CssmOwnedData &fieldValue) // RETURNED
555 {
556 if(!tbsGetCheck(cert.certificateToSign->issuer, index)) {
557 return false;
558 }
559 return getField_normRDN(*cert.certificateToSign->issuer, numFields, fieldValue);
560 }
561
562
563 /***
564 *** TBS AlgId, Signature AlgId
565 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
566 ***
567 *** common code:
568 ***/
569 static void getField_AlgId (
570 const AlgorithmIdentifier *snaccAlgId,
571 CssmOwnedData &fieldValue) // RETURNED
572 {
573 CssmAllocator &alloc = fieldValue.allocator;
574 fieldValue.malloc(sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
575 CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId =
576 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
577 CL_snaccAlgIdToCssm (*snaccAlgId, *cssmAlgId, alloc);
578 }
579
580 static void setField_AlgId (
581 AlgorithmIdentifier *snaccAlgId,
582 const CssmData &fieldValue)
583 {
584 CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId =
585 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
586 if(cssmAlgId->algorithm.Data == NULL) {
587 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
588 }
589 CL_cssmAlgIdToSnacc(*cssmAlgId, *snaccAlgId);
590 }
591
592 static void freeField_AlgId (
593 CssmOwnedData &fieldValue)
594 {
595 CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId =
596 (CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
597 if(cssmAlgId == NULL) {
598 return;
599 }
600 if(fieldValue.length() != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) {
601 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
602 }
603 CssmAllocator &alloc = fieldValue.allocator;
604 alloc.free(cssmAlgId->algorithm.Data);
605 alloc.free(cssmAlgId->parameters.Data);
606 memset(cssmAlgId, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
607 }
608
609
610 /* TBS AlgId */
611 static bool getField_TbsAlgId (
612 const DecodedCert &cert,
613 unsigned index, // which occurrence (0 = first)
614 uint32 &numFields, // RETURNED
615 CssmOwnedData &fieldValue) // RETURNED
616 {
617 AlgorithmIdentifier *snaccAlgId = cert.certificateToSign->signature;
618 if(!tbsGetCheck(snaccAlgId, index)) {
619 return false;
620 }
621 getField_AlgId(snaccAlgId, fieldValue);
622 numFields = 1;
623 return true;
624 }
625
626 static void setField_TbsAlgId (
627 DecodedCert &cert,
628 const CssmData &fieldValue)
629 {
630 tbsSetCheck(cert.certificateToSign->signature, fieldValue,
631 sizeof(CSSM_X509_ALGORITHM_IDENTIFIER), "TBS_AlgId");
632 AlgorithmIdentifier *snaccAlgId = new AlgorithmIdentifier;
633 cert.certificateToSign->signature = snaccAlgId;
634 setField_AlgId(snaccAlgId, fieldValue);
635 }
636
637 /* Cert AlgId - read only */
638 static bool getField_CertAlgId (
639 const DecodedCert &cert,
640 unsigned index, // which occurrence (0 = first)
641 uint32 &numFields, // RETURNED
642 CssmOwnedData &fieldValue) // RETURNED
643 {
644 AlgorithmIdentifier *snaccAlgId = cert.algorithmIdentifier;
645 if(!tbsGetCheck(snaccAlgId, index)) {
646 return false;
647 }
648 getField_AlgId(snaccAlgId, fieldValue);
649 numFields = 1;
650 return true;
651 }
652
653 /***
654 *** Validity not before, not after
655 *** Format: CSSM_X509_TIME
656 ***/
657
658 /*** common code ***/
659 static void getField_Time (
660 const Time *snaccTime,
661 CssmOwnedData &fieldValue) // RETURNED
662 {
663 CssmAllocator &alloc = fieldValue.allocator;
664 fieldValue.malloc(sizeof(CSSM_X509_TIME));
665 CSSM_X509_TIME *cssmTime =
666 (CSSM_X509_TIME *)fieldValue.data();
667 memset(cssmTime, 0, sizeof(CSSM_X509_TIME));
668
669 char *timeStr = NULL;
670 int timeStrLen = 0;
671 switch(snaccTime->choiceId) {
672 case Time::utcTimeCid:
673 cssmTime->timeType = BER_TAG_UTC_TIME;
674 timeStr = *snaccTime->utcTime; // an AsnOct
675 timeStrLen = snaccTime->utcTime->Len();
676 break;
677 case Time::generalizedTimeCid:
678 timeStr = *snaccTime->generalizedTime; // an AsnOct
679 timeStrLen = snaccTime->generalizedTime->Len();
680 cssmTime->timeType = BER_TAG_GENERALIZED_TIME;
681 break;
682 default:
683 /* snacc error, should never happen */
684 cssmTime->timeType = BER_TAG_OCTET_STRING;
685 timeStr = *snaccTime->generalizedTime; // an AsnOct
686 timeStrLen = snaccTime->generalizedTime->Len();
687 break;
688 }
689
690 cssmTime->time.Data = reinterpret_cast<uint8 *>(alloc.malloc(timeStrLen));
691 cssmTime->time.Length = timeStrLen;
692 memcpy(cssmTime->time.Data, timeStr, timeStrLen);
693 }
694
695 static void setField_Time (
696 Time *snaccTime,
697 const CssmData &fieldValue)
698 {
699 CSSM_X509_TIME *cssmTime =
700 (CSSM_X509_TIME *)fieldValue.data();
701 const char *tStr = reinterpret_cast<const char *>(cssmTime->time.Data);
702 size_t tLen = cssmTime->time.Length;
703
704 switch(cssmTime->timeType) {
705 case BER_TAG_GENERALIZED_TIME:
706 snaccTime->choiceId = Time::generalizedTimeCid;
707 snaccTime->generalizedTime = new GeneralizedTime(tStr, tLen);
708 break;
709 case BER_TAG_UTC_TIME:
710 snaccTime->choiceId = Time::utcTimeCid;
711 snaccTime->utcTime = new UTCTime(tStr, tLen);
712 break;
713 default:
714 errorLog1("setField_Time: bad time tag (%d)\n", cssmTime->timeType);
715 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
716 }
717 }
718
719 static void freeField_Time (
720 CssmOwnedData &fieldValue)
721 {
722 CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)fieldValue.data();
723 if(cssmTime == NULL) {
724 return;
725 }
726 if(fieldValue.length() != sizeof(CSSM_X509_TIME)) {
727 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
728 }
729 fieldValue.allocator.free(cssmTime->time.Data);
730 memset(cssmTime, 0, sizeof(CSSM_X509_TIME));
731 }
732
733 /*** not before ***/
734 static bool getField_NotBefore (
735 const DecodedCert &cert,
736 unsigned index, // which occurrence (0 = first)
737 uint32 &numFields, // RETURNED
738 CssmOwnedData &fieldValue) // RETURNED
739 {
740 if(!tbsGetCheck(cert.certificateToSign->validity, index)) {
741 return false;
742 }
743 if(cert.certificateToSign->validity->notBefore == NULL) {
744 return false;
745 }
746 getField_Time(cert.certificateToSign->validity->notBefore, fieldValue);
747 numFields = 1;
748 return true;
749 }
750
751 static void setField_NotBefore (
752 DecodedCert &cert,
753 const CssmData &fieldValue)
754 {
755 /* anything could need mallocing except TBS */
756 if(cert.certificateToSign->validity == NULL) {
757 cert.certificateToSign->validity = new Validity;
758 }
759 tbsSetCheck(cert.certificateToSign->validity->notBefore, fieldValue,
760 sizeof(CSSM_X509_TIME), "NotBefore");
761 cert.certificateToSign->validity->notBefore = new Time;
762 setField_Time(cert.certificateToSign->validity->notBefore, fieldValue);
763 }
764
765 /*** not after ***/
766 static bool getField_NotAfter (
767 const DecodedCert &cert,
768 unsigned index, // which occurrence (0 = first)
769 uint32 &numFields, // RETURNED
770 CssmOwnedData &fieldValue) // RETURNED
771 {
772 if(!tbsGetCheck(cert.certificateToSign->validity, index)) {
773 return false;
774 }
775 if(cert.certificateToSign->validity->notAfter == NULL) {
776 return false;
777 }
778 getField_Time(cert.certificateToSign->validity->notAfter, fieldValue);
779 numFields = 1;
780 return true;
781 }
782
783 static void setField_NotAfter (
784 DecodedCert &cert,
785 const CssmData &fieldValue)
786 {
787 /* anything could need mallocing except TBS */
788 if(cert.certificateToSign->validity == NULL) {
789 cert.certificateToSign->validity = new Validity;
790 }
791 tbsSetCheck(cert.certificateToSign->validity->notAfter, fieldValue,
792 sizeof(CSSM_X509_TIME), "NotAfter");
793 cert.certificateToSign->validity->notAfter = new Time;
794 setField_Time(cert.certificateToSign->validity->notAfter, fieldValue);
795 }
796
797 /***
798 *** Subject/issuer unique ID
799 *** Format: Raw bytes. It's stored in the cert as an ASN bit string; the decoded
800 *** bytes are present at this level (i.e., not tag and length in the bytes).
801 *** NOTE: this is not quite accurate in that we only provide byte-aligned size,
802 *** not bit-aligned. This field is rarely if ever used so I think it's O, but
803 *** beware.
804 ***/
805 static bool getField_SubjectUniqueId (
806 const DecodedCert &cert,
807 unsigned index, // which occurrence (0 = first)
808 uint32 &numFields, // RETURNED
809 CssmOwnedData &fieldValue) // RETURNED
810 {
811 UniqueIdentifier *id = cert.certificateToSign->subjectUniqueIdentifier;
812 if(!tbsGetCheck(id, index)) {
813 return false;
814 }
815 SC_asnBitsToCssmData(*id, fieldValue);
816 numFields = 1;
817 return true;
818 }
819
820 static void setField_SubjectUniqueId (
821 DecodedCert &cert,
822 const CssmData &fieldValue)
823 {
824 tbsSetCheck(cert.certificateToSign->subjectUniqueIdentifier, fieldValue, 0,
825 "SubjectUniqueID");
826 cert.certificateToSign->subjectUniqueIdentifier = new UniqueIdentifier(
827 reinterpret_cast<char * const>(fieldValue.Data), fieldValue.Length * 8);
828 }
829
830 static bool getField_IssuerUniqueId (
831 const DecodedCert &cert,
832 unsigned index, // which occurrence (0 = first)
833 uint32 &numFields, // RETURNED
834 CssmOwnedData &fieldValue) // RETURNED
835 {
836 UniqueIdentifier *id = cert.certificateToSign->issuerUniqueIdentifier;
837 if(!tbsGetCheck(id, index)) {
838 return false;
839 }
840 SC_asnBitsToCssmData(*id, fieldValue);
841 numFields = 1;
842 return true;
843 }
844
845 static void setField_IssuerUniqueId (
846 DecodedCert &cert,
847 const CssmData &fieldValue)
848 {
849 tbsSetCheck(cert.certificateToSign->issuerUniqueIdentifier, fieldValue, 0,
850 "IssuerniqueID");
851 cert.certificateToSign->issuerUniqueIdentifier = new UniqueIdentifier(
852 reinterpret_cast<char * const>(fieldValue.Data), fieldValue.Length * 8);
853 }
854
855 /***
856 *** Public key info
857 *** Format = CSSM_X509_SUBJECT_PUBLIC_KEY_INFO
858 ***/
859 static bool getField_PublicKeyInfo (
860 const DecodedCert &cert,
861 unsigned index, // which occurrence (0 = first)
862 uint32 &numFields, // RETURNED
863 CssmOwnedData &fieldValue) // RETURNED
864 {
865 if(!tbsGetCheck(cert.certificateToSign->subjectPublicKeyInfo, index)) {
866 return false;
867 }
868 SubjectPublicKeyInfo *snaccKeyInfo = cert.certificateToSign->subjectPublicKeyInfo;
869 AlgorithmIdentifier *snaccAlgId = snaccKeyInfo->algorithm;
870 if(snaccAlgId == NULL) {
871 errorLog0("getField_PublicKeyInfo: cert has pubKeyInfo but no algorithm!\n");
872 return false;
873 }
874 CssmAllocator &alloc = fieldValue.allocator;
875 fieldValue.malloc(sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));
876 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo =
877 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();
878 memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));
879 CL_snaccAlgIdToCssm(*snaccAlgId, cssmKeyInfo->algorithm, alloc);
880
881 /*
882 * key info - the actual public key blob - is stored in the cert as a bit string;
883 * snacc will give us the actual bits which are invariably yet another DER
884 * encoding (e.g., PKCS1 for RSA public keys).
885 */
886 size_t keyLen = (snaccKeyInfo->subjectPublicKey.BitLen() + 7) / 8;
887 cssmKeyInfo->subjectPublicKey.Data = (uint8 *)alloc.malloc(keyLen);
888 cssmKeyInfo->subjectPublicKey.Length = keyLen;
889 memcpy(cssmKeyInfo->subjectPublicKey.Data,
890 snaccKeyInfo->subjectPublicKey.BitOcts(),
891 keyLen);
892 numFields = 1;
893 return true;
894 }
895
896 static void setField_PublicKeyInfo (
897 DecodedCert &cert,
898 const CssmData &fieldValue)
899 {
900 /* This fails if setField_PublicKeyStruct has already been called */
901 tbsSetCheck(cert.certificateToSign->subjectPublicKeyInfo, fieldValue,
902 sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO), "PubKeyInfo");
903 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo =
904 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.Data;
905 if((cssmKeyInfo->subjectPublicKey.Data == NULL) ||
906 (cssmKeyInfo->subjectPublicKey.Length == 0)) {
907 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
908 }
909
910 SubjectPublicKeyInfo *snaccKeyInfo = new SubjectPublicKeyInfo;
911 cert.certificateToSign->subjectPublicKeyInfo = snaccKeyInfo;
912 snaccKeyInfo->algorithm = new AlgorithmIdentifier;
913
914 /* common code to convert algorithm info (algID and parameters) */
915 const CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId = &cssmKeyInfo->algorithm;
916 CL_cssmAlgIdToSnacc(*cssmAlgId, *snaccKeyInfo->algorithm);
917
918 /* actual public key blob - AsnBits */
919 snaccKeyInfo->subjectPublicKey.Set(reinterpret_cast<char *>
920 (cssmKeyInfo->subjectPublicKey.Data),
921 cssmKeyInfo->subjectPublicKey.Length);
922
923 }
924 static void freeField_PublicKeyInfo (
925 CssmOwnedData &fieldValue)
926 {
927 CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *cssmKeyInfo =
928 (CSSM_X509_SUBJECT_PUBLIC_KEY_INFO *)fieldValue.data();
929 if(cssmKeyInfo == NULL) {
930 return;
931 }
932 CssmAllocator &alloc = fieldValue.allocator;
933 CSSM_X509_ALGORITHM_IDENTIFIER *algId = &cssmKeyInfo->algorithm;
934 alloc.free(algId->algorithm.Data);
935 alloc.free(algId->parameters.Data);
936 alloc.free(cssmKeyInfo->subjectPublicKey.Data);
937 memset(cssmKeyInfo, 0, sizeof(CSSM_X509_SUBJECT_PUBLIC_KEY_INFO));}
938
939 /***
940 *** key info from CSSM_KEY
941 *** Format = CSSM_KEY
942 ***/
943 static bool getField_PublicKeyStruct (
944 const DecodedCert &cert,
945 unsigned index, // which occurrence (0 = first)
946 uint32 &numFields, // RETURNED
947 CssmOwnedData &fieldValue) // RETURNED
948 {
949 if(!tbsGetCheck(cert.certificateToSign->subjectPublicKeyInfo, index)) {
950 return false;
951 }
952 CSSM_KEY_PTR cssmKey = cert.extractCSSMKey(fieldValue.allocator);
953 fieldValue.set(reinterpret_cast<uint8 *>(cssmKey), sizeof(CSSM_KEY));
954 numFields = 1;
955 return true;
956 }
957
958 static void setField_PublicKeyStruct (
959 DecodedCert &cert,
960 const CssmData &fieldValue)
961 {
962 /* This fails if setField_PublicKeyInfo has already been called */
963 tbsSetCheck(cert.certificateToSign->subjectPublicKeyInfo, fieldValue,
964 sizeof(CSSM_KEY), "PubKey");
965 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
966 if((cssmKey->KeyData.Data == NULL) ||
967 (cssmKey->KeyData.Data == 0)) {
968 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
969 }
970
971 SubjectPublicKeyInfo *snaccKeyInfo = new SubjectPublicKeyInfo;
972 cert.certificateToSign->subjectPublicKeyInfo = snaccKeyInfo;
973 snaccKeyInfo->algorithm = new AlgorithmIdentifier;
974 CL_cssmAlgToSnaccOid(cssmKey->KeyHeader.AlgorithmId,
975 snaccKeyInfo->algorithm->algorithm);
976
977 /* NULL algorithm paramneters, always in this case */
978 CL_nullAlgParams(*snaccKeyInfo->algorithm);
979
980 /* actual public key blob - AsnBits */
981 /***
982 *** TBD FIXME if this key is a ref key, null wrap it to a raw key
983 ***/
984 if(cssmKey->KeyHeader.BlobType != CSSM_KEYBLOB_RAW) {
985 errorLog0("CL SetField: must specify RAW key blob\n");
986 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER);
987 }
988 snaccKeyInfo->subjectPublicKey.Set(reinterpret_cast<char *>
989 (cssmKey->KeyData.Data), cssmKey->KeyData.Length * 8);
990 }
991
992 static void freeField_PublicKeyStruct (
993 CssmOwnedData &fieldValue)
994 {
995 CSSM_KEY_PTR cssmKey = (CSSM_KEY_PTR)fieldValue.data();
996 DecodedCert::freeCSSMKey(cssmKey, fieldValue.allocator, false);
997 }
998
999 /***
1000 *** Signature
1001 *** Format = raw bytes
1002 *** read-only
1003 ***/
1004 static bool getField_Signature (
1005 const DecodedCert &cert,
1006 unsigned index, // which occurrence (0 = first)
1007 uint32 &numFields, // RETURNED
1008 CssmOwnedData &fieldValue) // RETURNED
1009 {
1010 if((index > 0) || // max of one sig
1011 (cert.signatureValue.BitLen() == 0)) { // no sig - must be TBS only
1012 return false;
1013 }
1014 SC_asnBitsToCssmData(cert.signatureValue, fieldValue);
1015 numFields = 1;
1016 return true;
1017 }
1018
1019 /***
1020 *** end of field-specific triplets
1021 ***/
1022
1023 /* setField for read-only OIDs (i.e., the ones in cert, not TBS) */
1024 static void setField_ReadOnly (
1025 DecodedCert &cert,
1026 const CssmData &fieldValue)
1027 {
1028 errorLog0("Attempt to set a read-only field\n");
1029 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
1030 }
1031
1032 /*
1033 * Table to map OID to {get,set,free}field
1034 */
1035 typedef struct {
1036 const CSSM_OID *fieldId;
1037 getFieldFcn *getFcn;
1038 setFieldFcn *setFcn;
1039 freeFieldFcn *freeFcn; // OPTIONAL - NULL means just free the
1040 // top-level data
1041 } oidToFieldFuncs;
1042
1043 static const oidToFieldFuncs fieldFuncTable[] = {
1044 { &CSSMOID_X509V1Version,
1045 &getField_Version, &setField_Version, NULL },
1046 { &CSSMOID_X509V1SerialNumber,
1047 &getField_SerialNumber, &setField_SerialNumber, NULL },
1048 { &CSSMOID_X509V1IssuerNameCStruct,
1049 &getField_Issuer, &setField_Issuer, &freeField_RDN },
1050 { &CSSMOID_X509V1SubjectNameCStruct,
1051 &getField_Subject, &setField_Subject, &freeField_RDN },
1052 { &CSSMOID_X509V1SignatureAlgorithmTBS,
1053 &getField_TbsAlgId, &setField_TbsAlgId, &freeField_AlgId },
1054 { &CSSMOID_X509V1SignatureAlgorithm,
1055 &getField_CertAlgId, &setField_ReadOnly, &freeField_AlgId },
1056 { &CSSMOID_X509V1ValidityNotBefore,
1057 &getField_NotBefore, &setField_NotBefore, &freeField_Time },
1058 { &CSSMOID_X509V1ValidityNotAfter,
1059 &getField_NotAfter, &setField_NotAfter, &freeField_Time },
1060 { &CSSMOID_X509V1CertificateIssuerUniqueId,
1061 &getField_IssuerUniqueId, &setField_IssuerUniqueId, NULL },
1062 { &CSSMOID_X509V1CertificateSubjectUniqueId,
1063 &getField_SubjectUniqueId, &setField_SubjectUniqueId, NULL },
1064 { &CSSMOID_X509V1SubjectPublicKeyCStruct,
1065 &getField_PublicKeyInfo, &setField_PublicKeyInfo, &freeField_PublicKeyInfo },
1066 { &CSSMOID_CSSMKeyStruct,
1067 &getField_PublicKeyStruct, &setField_PublicKeyStruct,
1068 &freeField_PublicKeyStruct },
1069 { &CSSMOID_X509V1Signature,
1070 &getField_Signature, &setField_ReadOnly, NULL },
1071 { &CSSMOID_X509V1IssuerName,
1072 getFieldIssuerNorm, &setField_ReadOnly, NULL },
1073 { &CSSMOID_X509V1SubjectName,
1074 getFieldSubjectNorm, &setField_ReadOnly, NULL },
1075
1076 /*
1077 * Extensions, implemented in CertExtensions.cpp
1078 * When adding new ones, also add to:
1079 * -- oidToSnaccObj() in CertExtensions.cpp
1080 * -- get/set/free functions in CertExtensions.{cpp,h}
1081 */
1082 { &CSSMOID_KeyUsage, &getFieldKeyUsage, &setFieldKeyUsage,
1083 &freeFieldSimpleExtension },
1084 { &CSSMOID_BasicConstraints, &getFieldBasicConstraints,
1085 &setFieldBasicConstraints, &freeFieldSimpleExtension },
1086 { &CSSMOID_ExtendedKeyUsage, &getFieldExtKeyUsage,
1087 &setFieldExtKeyUsage, &freeFieldExtKeyUsage } ,
1088 { &CSSMOID_SubjectKeyIdentifier, &getFieldSubjectKeyId,
1089 &setFieldSubjectKeyId, &freeFieldSubjectKeyId } ,
1090 { &CSSMOID_AuthorityKeyIdentifier, &getFieldAuthorityKeyId,
1091 &setFieldAuthorityKeyId, &freeFieldAuthorityKeyId } ,
1092 { &CSSMOID_SubjectAltName, &getFieldSubjAltName,
1093 &setFieldSubjAltName, &freeFieldSubjAltName } ,
1094 { &CSSMOID_CertificatePolicies, &getFieldCertPolicies,
1095 &setFieldCertPolicies, &freeFieldCertPolicies } ,
1096 { &CSSMOID_NetscapeCertType, &getFieldNetscapeCertType,
1097 &setFieldNetscapeCertType, &freeFieldSimpleExtension } ,
1098 { &CSSMOID_X509V3CertificateExtensionCStruct, &getFieldUnknownExt,
1099 &setFieldUnknownExt, &freeFieldUnknownExt }
1100 };
1101
1102 #define NUM_KNOWN_FIELDS (sizeof(fieldFuncTable) / sizeof(oidToFieldFuncs))
1103 #define NUM_STD_CERT_FIELDS 13 /* not including extensions */
1104
1105
1106 /* map an OID to an oidToFieldFuncs */
1107 static const oidToFieldFuncs *oidToFields(
1108 const CssmOid &fieldId)
1109 {
1110 const oidToFieldFuncs *funcPtr = fieldFuncTable;
1111
1112 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
1113 if(fieldId == CssmData::overlay(*funcPtr->fieldId)) {
1114 return funcPtr;
1115 }
1116 funcPtr++;
1117 }
1118 CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
1119 }
1120
1121
1122 /***
1123 *** Public functions
1124 ***/
1125
1126 /*
1127 * Obtain the index'th occurrence of field specified by fieldId in specified cert.
1128 * Format of the returned field depends on fieldId.
1129 * Returns total number of fieldId fields in the cert if index is 0.
1130 * FieldValue assumed to be empty on entry.
1131 * Returns true if specified field was found, else returns false.
1132 */
1133 bool DecodedCert::getCertFieldData(
1134 const CssmOid &fieldId, // which field
1135 unsigned index, // which occurrence (0 = first)
1136 uint32 &numFields, // RETURNED
1137 CssmOwnedData &fieldValue) const // RETURNED
1138 {
1139 CASSERT(certificateToSign != NULL);
1140 switch(mState) {
1141 case CS_Empty:
1142 case CS_Building:
1143 errorLog0("DecodedCert::getCertField: can't parse undecoded cert!\n");
1144 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
1145 case CS_DecodedCert:
1146 case CS_DecodedTBS:
1147 break;
1148 }
1149 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
1150 return fieldFuncs->getFcn(*this, index, numFields, fieldValue);
1151 }
1152
1153 /*
1154 * Set the field specified by fieldId in the specified Cert.
1155 * Note no index - individual field routines either append (for extensions)
1156 * or if field already set ::throwMe(for all others)
1157 */
1158 void DecodedCert::setCertField(
1159 const CssmOid &fieldId, // which field
1160 const CssmData &fieldValue)
1161 {
1162 CASSERT(certificateToSign != NULL);
1163 switch(mState) {
1164 case CS_Empty: // first time thru
1165 mState = CS_Building;
1166 break;
1167 case CS_Building: // subsequent passes
1168 break;
1169 case CS_DecodedCert:
1170 case CS_DecodedTBS:
1171 errorLog0("DecodedCert::setCertField: can't build on a decoded cert!\n");
1172 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
1173 }
1174 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
1175 CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
1176 }
1177 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
1178 const CssmData &value = CssmData::overlay(fieldValue);
1179 fieldFuncs->setFcn(*this, value);
1180 }
1181
1182 /*
1183 * Free the fieldId-specific data referred to by fieldValue->Data.
1184 */
1185 void DecodedCert::freeCertFieldData(
1186 const CssmOid &fieldId,
1187 CssmOwnedData &fieldValue)
1188 {
1189 if((fieldValue.data() == NULL) || (fieldValue.length() == 0)) {
1190 CssmError::throwMe(CSSM_ERRCODE_INVALID_FIELD_POINTER);
1191 }
1192 const oidToFieldFuncs *fieldFuncs = oidToFields(fieldId);
1193 if(fieldFuncs->freeFcn != NULL) {
1194 /* optional - simple cases handled below */
1195 fieldFuncs->freeFcn(fieldValue);
1196 }
1197 fieldValue.reset();
1198 fieldValue.release();
1199
1200 }
1201
1202
1203 /*
1204 * Common means to get all fields from a decoded cert. Used in
1205 * CertGetAllTemplateFields and CertGetAllFields.
1206 */
1207 void DecodedCert::getAllParsedCertFields(
1208 uint32 &NumberOfFields, // RETURNED
1209 CSSM_FIELD_PTR &CertFields) // RETURNED
1210 {
1211 /* this is the max - some might be missing */
1212 uint32 maxFields = NUM_STD_CERT_FIELDS + mNumExtensions;
1213 CSSM_FIELD_PTR outFields = (CSSM_FIELD_PTR)malloc(maxFields * sizeof(CSSM_FIELD));
1214
1215 /*
1216 * We'll be copying oids and values for fields we find into
1217 * outFields; current number of valid fields found in numOutFields.
1218 */
1219 memset(outFields, 0, maxFields * sizeof(CSSM_FIELD));
1220 uint32 numOutFields = 0;
1221 CSSM_FIELD_PTR currOutField;
1222 uint32 currOidDex;
1223 const CSSM_OID *currOid;
1224 CssmAutoData aData(alloc); // for malloc/copy of outgoing data
1225
1226 /* query for each OID we know about */
1227 for(currOidDex=0; currOidDex<NUM_KNOWN_FIELDS; currOidDex++) {
1228 const oidToFieldFuncs *fieldFuncs = &fieldFuncTable[currOidDex];
1229 currOid = fieldFuncs->fieldId;
1230 uint32 numFields; // for THIS oid
1231
1232 /*
1233 * Return false if field not there, which is not an error here.
1234 * Actual exceptions are fatal.
1235 */
1236 if(!fieldFuncs->getFcn(*this,
1237 0, // index - looking for first one
1238 numFields,
1239 aData)) {
1240 continue;
1241 }
1242
1243 /* got some data for this oid - copy it and oid to outgoing CertFields */
1244 CASSERT(numOutFields < maxFields);
1245 currOutField = &outFields[numOutFields];
1246 currOutField->FieldValue = aData.release();
1247 aData.copy(*currOid);
1248 currOutField->FieldOid = aData.release();
1249 numOutFields++;
1250
1251 /* if more fields are available for this OID, snag them too */
1252 for(uint32 fieldDex=1; fieldDex<numFields; fieldDex++) {
1253 /* note this should always succeed */
1254 bool brtn = fieldFuncs->getFcn(*this,
1255 fieldDex,
1256 numFields, // shouldn't change
1257 aData);
1258 if(!brtn) {
1259 errorLog0("getAllParsedCertFields: index screwup\n");
1260 CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
1261 }
1262 CASSERT(numOutFields < maxFields);
1263 currOutField = &outFields[numOutFields];
1264 currOutField->FieldValue = aData.release();
1265 aData.copy(*currOid);
1266 currOutField->FieldOid = aData.release();
1267 numOutFields++;
1268 } /* multiple fields for currOid */
1269 } /* for each known OID */
1270
1271 NumberOfFields = numOutFields;
1272 CertFields = outFields;
1273 }
1274
1275 void
1276 DecodedCert::describeFormat(
1277 CssmAllocator &alloc,
1278 uint32 &NumberOfFields,
1279 CSSM_OID_PTR &OidList)
1280 {
1281 /* malloc in app's space, do deep copy (including ->Data) */
1282 CSSM_OID_PTR oidList = (CSSM_OID_PTR)alloc.malloc(
1283 NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
1284 memset(oidList, 0, NUM_KNOWN_FIELDS * sizeof(CSSM_OID));
1285 for(unsigned i=0; i<NUM_KNOWN_FIELDS; i++) {
1286 CssmAutoData oidCopy(alloc, *fieldFuncTable[i].fieldId);
1287 oidList[i] = oidCopy.release();
1288 }
1289 NumberOfFields = NUM_KNOWN_FIELDS;
1290 OidList = oidList;
1291 }