1/*
2 * Copyright (c) 2002-2011 Apple 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 * CLFieldsCommon.h - get/set/free routines common to certs and CRLs
21 */
22
23#include "CLFieldsCommon.h"
24#include "clNameUtils.h"
25#include "clNssUtils.h"
26#include "AppleX509CLSession.h"
27#include <Security/cssmapple.h>
28#include <Security/oidscert.h>
29#include <Security/nameTemplates.h>
30#include <Security/certExtensionTemplates.h>
31#include <Security/SecAsn1Templates.h>
32
33/*
34 * Table to map an OID to the info needed to decode the
35 * associated extension
36 */
37typedef struct {
38	const CSSM_OID 			&oid;
39	unsigned				nssObjLen;
40	const SecAsn1Template	*templ;
41} NssExtenInfo;
42
43static const NssExtenInfo nssExtenInfo[] = {
44	{ CSSMOID_KeyUsage,
45	  sizeof(CSSM_DATA),
46	  kSecAsn1KeyUsageTemplate },
47	{ CSSMOID_BasicConstraints,
48	  sizeof(NSS_BasicConstraints),
49	  kSecAsn1BasicConstraintsTemplate },
50	{ CSSMOID_ExtendedKeyUsage,
51	  sizeof(NSS_ExtKeyUsage),
52	  kSecAsn1ExtKeyUsageTemplate },
53	{ CSSMOID_SubjectKeyIdentifier,
54	  sizeof(CSSM_DATA),
55	  kSecAsn1SubjectKeyIdTemplate },
56	{ CSSMOID_AuthorityKeyIdentifier,
57	  sizeof(NSS_AuthorityKeyId),
58	  kSecAsn1AuthorityKeyIdTemplate },
59	{ CSSMOID_SubjectAltName,
60	  sizeof(NSS_GeneralNames),
61	  kSecAsn1GeneralNamesTemplate },
62	{ CSSMOID_IssuerAltName,
63	  sizeof(NSS_GeneralNames),
64	  kSecAsn1GeneralNamesTemplate },
65	{ CSSMOID_CertificatePolicies,
66	  sizeof(NSS_CertPolicies),
67	  kSecAsn1CertPoliciesTemplate },
68	{ CSSMOID_NetscapeCertType,
69	  sizeof(CSSM_DATA),
70	  kSecAsn1NetscapeCertTypeTemplate },
71	{ CSSMOID_CrlDistributionPoints,
72	  sizeof(NSS_CRLDistributionPoints),
73	  kSecAsn1CRLDistributionPointsTemplate },
74	{ CSSMOID_CertIssuer,
75	  sizeof(NSS_GeneralNames),
76	  kSecAsn1GeneralNamesTemplate },
77	{ CSSMOID_AuthorityInfoAccess,
78	  sizeof(NSS_AuthorityInfoAccess),
79	  kSecAsn1AuthorityInfoAccessTemplate },
80	{ CSSMOID_SubjectInfoAccess,
81	  sizeof(NSS_AuthorityInfoAccess),
82	  kSecAsn1AuthorityInfoAccessTemplate },
83	/* CRL extensions */
84	{ CSSMOID_CrlNumber,
85	  sizeof(CSSM_DATA),
86	  kSecAsn1IntegerTemplate },
87	{ CSSMOID_IssuingDistributionPoint,
88	  sizeof(NSS_IssuingDistributionPoint),
89	  kSecAsn1IssuingDistributionPointTemplate },
90	{ CSSMOID_HoldInstructionCode,
91	  sizeof(CSSM_OID),
92	  kSecAsn1ObjectIDTemplate },
93	{ CSSMOID_CrlReason,
94	  sizeof(CSSM_DATA),
95	  kSecAsn1EnumeratedTemplate },
96	{ CSSMOID_DeltaCrlIndicator,
97	  sizeof(CSSM_DATA),
98	  kSecAsn1IntegerTemplate },
99	{ CSSMOID_InvalidityDate,
100	  sizeof(CSSM_DATA),
101	  kSecAsn1GeneralizedTimeTemplate },
102	{ CSSMOID_QC_Statements,
103	  sizeof(NSS_QC_Statements),
104	  kSecAsn1QC_StatementsTemplate },
105	{ CSSMOID_NameConstraints,
106	  sizeof(NSS_NameConstraints),
107	  kSecAsn1NameConstraintsTemplate },
108	{ CSSMOID_PolicyMappings,
109	  sizeof(NSS_PolicyMappings),
110	  kSecAsn1PolicyMappingsTemplate },
111	{ CSSMOID_PolicyConstraints,
112	  sizeof(NSS_PolicyConstraints),
113	  kSecAsn1PolicyConstraintsTemplate },
114	{ CSSMOID_InhibitAnyPolicy,
115	  sizeof(CSSM_DATA),
116	  kSecAsn1IntegerTemplate },
117};
118
119#define NUM_NSS_EXTEN_INFOS	(sizeof(nssExtenInfo) / sizeof(nssExtenInfo[0]))
120
121/*
122 * Returns true if we find the OID.
123 */
124bool clOidToNssInfo(
125	const CSSM_OID			&oid,
126	unsigned				&nssObjLen,		// RETURNED
127	const SecAsn1Template	*&templ)		// RETURNED
128{
129	for(unsigned dex=0; dex<NUM_NSS_EXTEN_INFOS; dex++) {
130		const NssExtenInfo &info = nssExtenInfo[dex];
131		if(clCompareCssmData(&info.oid, &oid)) {
132			nssObjLen = info.nssObjLen;
133			templ = info.templ;
134			return true;
135		}
136	}
137	return false;
138}
139
140
141
142/*
143 * Common code to pass info from a DecodedExten back to app.
144 * Called from getField*().
145 */
146void getFieldExtenCommon(
147	void 				*cdsaObj,			// e.g. CE_KeyUsage
148											// NULL for berEncoded
149	const DecodedExten	&decodedExt,
150	CssmOwnedData		&fieldValue)
151{
152	CSSM_X509_EXTENSION_PTR cssmExt;
153	Allocator &alloc = fieldValue.allocator;
154	CssmData &fdata = fieldValue.get();
155
156	cssmExt = (CSSM_X509_EXTENSION_PTR)alloc.
157		malloc(sizeof(CSSM_X509_EXTENSION));
158	fdata.Data = (uint8 *)cssmExt;
159	fdata.Length = sizeof(CSSM_X509_EXTENSION);
160	decodedExt.convertToCdsa(cdsaObj, cssmExt, alloc);
161}
162
163/*
164 * Common code for top of setField* and freeField*().
165 */
166CSSM_X509_EXTENSION_PTR verifySetFreeExtension(
167	const CssmData &fieldValue,
168	bool berEncoded)		// false: value in value.parsedValue
169							// true : value in BERValue
170{
171	if(fieldValue.length() != sizeof(CSSM_X509_EXTENSION)) {
172		clFieldLog("Set/FreeExtension: bad length : exp %d got %d",
173			(int)sizeof(CSSM_X509_EXTENSION), (int)fieldValue.length());
174		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
175	}
176	CSSM_X509_EXTENSION_PTR cssmExt =
177		reinterpret_cast<CSSM_X509_EXTENSION_PTR>(fieldValue.data());
178	if(berEncoded) {
179		if(cssmExt->BERvalue.Data == NULL) {
180			CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
181		}
182	}
183	else {
184		if(cssmExt->value.parsedValue == NULL) {
185			CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
186		}
187	}
188	return cssmExt;
189}
190
191/*
192 * Common free code for all extensions. Extension-specific code must
193 * free anything beyond cdsaExt->Value.parsedValue, then we free everything
194 * else (except the extension struct itself, which is freed by
195 * DecodedCert::freeCertFieldData()).
196 * The value union may contain a parsed value, or a CSSM_X509EXT_TAGandVALUE;
197 * wed ont' care, we just free it.
198 */
199void freeFieldExtenCommon(
200	CSSM_X509_EXTENSION_PTR	exten,
201	Allocator			&alloc)
202{
203	alloc.free(exten->extnId.Data);
204	alloc.free(exten->BERvalue.Data);		// may be NULL
205	alloc.free(exten->value.parsedValue);   // may be NULL
206}
207
208/*
209 * One common free for extensions whose parsed value doesn't go any deeper
210 * than cssmExt->value.parsedValue.
211 */
212void freeFieldSimpleExtension (
213	CssmOwnedData		&fieldValue)
214{
215	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue,
216		false);
217	freeFieldExtenCommon(cssmExt, fieldValue.allocator);
218}
219
220
221/***
222 *** Common code for get/set subject/issuer name (C struct version)
223 *** Format = CSSM_X509_NAME
224 *** class Name from sm_x501if
225 ***/
226bool getField_RDN_NSS (
227	const NSS_Name 		&nssName,
228	CssmOwnedData		&fieldValue)	// RETURNED
229{
230	/* alloc top-level CSSM_X509_NAME */
231	Allocator &alloc = fieldValue.allocator;
232	fieldValue.malloc(sizeof(CSSM_X509_NAME));
233	CSSM_X509_NAME_PTR cssmName = (CSSM_X509_NAME_PTR)fieldValue.data();
234
235	CL_nssNameToCssm(nssName, *cssmName, alloc);
236	return true;
237}
238
239void freeField_RDN  (
240	CssmOwnedData		&fieldValue)
241{
242	if(fieldValue.data() == NULL) {
243		return;
244	}
245	if(fieldValue.length() != sizeof(CSSM_X509_NAME)) {
246		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
247	}
248	Allocator &alloc = fieldValue.allocator;
249	CSSM_X509_NAME_PTR x509Name = (CSSM_X509_NAME_PTR)fieldValue.data();
250	CL_freeX509Name(x509Name, alloc);
251
252	/* top-level x509Name pointer freed by freeCertFieldData() */
253}
254
255/***
256 *** Common code for Issuer Name, Subject Name (normalized and encoded
257 *** version)
258 *** Format = CSSM_DATA containing the DER encoding of the normalized name
259 ***/
260bool getField_normRDN_NSS (
261	const CSSM_DATA		&derName,
262	uint32				&numFields,		// RETURNED (if successful, 0 or 1)
263	CssmOwnedData		&fieldValue)	// RETURNED
264{
265	if(derName.Data == NULL) {
266		/* This can happen during CertGetAllTemplateFields() because
267		 * the normalized fields are only set up during cert/CRL decode */
268		return false;
269	}
270
271	/*
272	 * First make a temp decoded copy which we'll be manipulating.
273	 */
274	SecNssCoder coder;
275	NSS_Name decodedName;
276
277	memset(&decodedName, 0, sizeof(decodedName));
278	PRErrorCode prtn = coder.decodeItem(derName, kSecAsn1NameTemplate, &decodedName);
279	if(prtn) {
280		/*
281		 * Actually should never happen since this same bag of bits successfully
282		 * decoded when the cert as a whole was decoded...
283		 */
284		clErrorLog("getField_normRDN decode error\n");
285		CssmError::throwMe(CSSMERR_CL_UNKNOWN_FORMAT);
286
287	}
288
289	/* normalize */
290	CL_normalizeX509NameNSS(decodedName, coder);
291
292	/* encode result */
293	prtn = SecNssEncodeItemOdata(&decodedName, kSecAsn1NameTemplate, fieldValue);
294	if(prtn) {
295		clErrorLog("getField_normRDN encode error\n");
296		CssmError::throwMe(CSSMERR_CL_INTERNAL_ERROR);
297	}
298	numFields = 1;
299	return true;
300}
301
302/***
303 *** Common code for Time fields - Validity not before, Not After,
304 ***    This Update, Next Update
305 *** Format: CSSM_X509_TIME
306 ***/
307bool getField_TimeNSS (
308	const NSS_Time 	&nssTime,
309	unsigned		index,			// which occurrence (0 = first)
310	uint32			&numFields,		// RETURNED
311	CssmOwnedData	&fieldValue)	// RETURNED
312{
313	if(!tbsGetCheck(nssTime.item.Data, index)) {
314		return false;
315	}
316	Allocator &alloc = fieldValue.allocator;
317	fieldValue.malloc(sizeof(CSSM_X509_TIME));
318	CSSM_X509_TIME *cssmTime =
319		(CSSM_X509_TIME *)fieldValue.data();
320	if(CL_nssTimeToCssm(nssTime, *cssmTime, alloc)) {
321		numFields = 1;
322		return true;
323	}
324	else {
325		return false;
326	}
327}
328
329void setField_TimeNSS (
330	const CssmData	&fieldValue,
331	NSS_Time		&nssTime,
332	SecNssCoder		&coder)
333{
334	CSSM_X509_TIME *cssmTime =
335		(CSSM_X509_TIME *)fieldValue.data();
336	CL_cssmTimeToNss(*cssmTime, nssTime, coder);
337}
338
339void freeField_Time (
340	CssmOwnedData		&fieldValue)
341{
342	CSSM_X509_TIME *cssmTime = (CSSM_X509_TIME *)fieldValue.data();
343	if(cssmTime == NULL) {
344		return;
345	}
346	if(fieldValue.length() != sizeof(CSSM_X509_TIME)) {
347		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
348	}
349	CL_freeCssmTime(cssmTime, fieldValue.allocator);
350}
351
352/***
353 *** TBS AlgId, Signature AlgId
354 *** Format = CSSM_X509_ALGORITHM_IDENTIFIER
355 ***/
356void getField_AlgIdNSS (
357	const CSSM_X509_ALGORITHM_IDENTIFIER 	&srcAlgId,
358	CssmOwnedData							&fieldValue)	// RETURNED
359{
360	Allocator &alloc = fieldValue.allocator;
361	fieldValue.malloc(sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
362	CSSM_X509_ALGORITHM_IDENTIFIER *destAlgId =
363		(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
364	CL_copyAlgId(srcAlgId, *destAlgId, alloc);
365}
366
367void setField_AlgIdNSS (
368	const CssmData		&fieldValue,
369	CSSM_X509_ALGORITHM_IDENTIFIER &dstAlgId,
370	SecNssCoder			&coder)
371{
372	CSSM_X509_ALGORITHM_IDENTIFIER *srcAlgId =
373		(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
374	/* allocator for this coder */
375	ArenaAllocator areanAlloc(coder);
376	CL_copyAlgId(*srcAlgId, dstAlgId, areanAlloc);
377}
378
379void freeField_AlgId (
380	CssmOwnedData		&fieldValue)
381{
382	CSSM_X509_ALGORITHM_IDENTIFIER *cssmAlgId =
383		(CSSM_X509_ALGORITHM_IDENTIFIER *)fieldValue.data();
384	if(cssmAlgId == NULL) {
385		return;
386	}
387	if(fieldValue.length() != sizeof(CSSM_X509_ALGORITHM_IDENTIFIER)) {
388		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
389	}
390	Allocator &alloc = fieldValue.allocator;
391	alloc.free(cssmAlgId->algorithm.Data);
392	alloc.free(cssmAlgId->parameters.Data);
393	memset(cssmAlgId, 0, sizeof(CSSM_X509_ALGORITHM_IDENTIFIER));
394}
395
396/*
397 * Routines for common validity checking for certificateToSign fields.
398 *
399 * Call from setField*: verify field isn't already set, optionally validate
400 * input length
401 */
402void tbsSetCheck(
403	void				*fieldToSet,
404	const CssmData		&fieldValue,
405	uint32				expLength,
406	const char			*op)
407{
408	if(fieldToSet != NULL) {
409		/* can't add another */
410		clErrorLog("setField(%s): field already set", op);
411		CssmError::throwMe(CSSMERR_CL_INVALID_NUMBER_OF_FIELDS);
412	}
413	if((expLength != 0) && (fieldValue.length() != expLength)) {
414		clErrorLog("setField(%s): bad length : exp %d got %d",
415			op, (int)expLength, (int)fieldValue.length());
416		CssmError::throwMe(CSSMERR_CL_INVALID_FIELD_POINTER);
417	}
418}
419
420/*
421 * Call from getField* for unique fields - detect missing field or
422 * index out of bounds.
423 */
424bool tbsGetCheck(
425	const void	*requiredField,
426	uint32		reqIndex)
427{
428	if((requiredField == NULL) ||  (reqIndex != 0)) {
429		return false;
430	}
431	else {
432		return true;
433	}
434}
435
436/***
437 *** unknown extensions
438 *** CDSA format: raw bytes in a CSSM_DATA. This data is the BER-encoding of
439 ***              some extension struct we don't know about.
440 *** NSS format   CSSM_DATA
441 *** OID 		  CSSMOID_X509V3CertificateExtensionCStruct
442 ***/
443
444void setFieldUnknownExt(
445	DecodedItem	&cert,
446	const CssmData &fieldValue)
447{
448	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
449	SecNssCoder &coder = cert.coder();
450	CSSM_DATA *rawExtn = (CSSM_DATA *)coder.malloc(sizeof(CSSM_DATA));
451	coder.allocCopyItem(cssmExt->BERvalue, *rawExtn);
452	cert.addExtension(NULL, cssmExt->extnId, cssmExt->critical,
453		true, NULL /* no template */, rawExtn);
454}
455
456bool getFieldUnknownExt(
457	DecodedItem 		&cert,
458	unsigned			index,			// which occurrence (0 = first)
459	uint32				&numFields,		// RETURNED
460	CssmOwnedData		&fieldValue)
461{
462	uint8 noOidDataLikeThis[2] = {1, 2};	// a dummy argument
463	CSSM_OID noOidLikeThis = {2, noOidDataLikeThis};
464	const DecodedExten *decodedExt =
465		cert.DecodedItem::findDecodedExt(noOidLikeThis,
466		true, index, numFields);
467	if(decodedExt == NULL) {
468		return false;
469	}
470	getFieldExtenCommon(NULL, *decodedExt, fieldValue);
471	return true;
472}
473
474void freeFieldUnknownExt (
475	CssmOwnedData		&fieldValue)
476{
477	CSSM_X509_EXTENSION_PTR cssmExt = verifySetFreeExtension(fieldValue, true);
478	Allocator &alloc = fieldValue.allocator;
479	freeFieldExtenCommon(cssmExt, alloc);		// frees extnId, parsedValue, BERvalue
480}
481
482/* setField for read-only OIDs (i.e., the ones in cert/CRL, not TBS) */
483void setField_ReadOnly (
484	DecodedItem			&item,
485	const CssmData		&fieldValue)
486{
487	clErrorLog("Attempt to set a read-only field");
488	CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
489}
490
491bool getField_Unimplemented (
492	DecodedItem			&item,
493	unsigned			index,			// which occurrence (0 = first)
494	uint32				&numFields,		// RETURNED
495	CssmOwnedData		&fieldValue)	// RETURNED
496{
497	clErrorLog("Attempt to get an unimplemented field");
498	CssmError::throwMe(CSSMERR_CL_UNKNOWN_TAG);
499}
500
501
502
503