1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | |
5 | /* |
6 | * cert.h - public data structures and prototypes for the certificate library |
7 | */ |
8 | |
9 | #ifndef _CERT_H_ |
10 | #define _CERT_H_ |
11 | |
12 | #include "utilrename.h" |
13 | #include "plarena.h" |
14 | #include "plhash.h" |
15 | #include "prlong.h" |
16 | #include "prlog.h" |
17 | |
18 | #include "seccomon.h" |
19 | #include "secdert.h" |
20 | #include "secoidt.h" |
21 | #include "keythi.h" |
22 | #include "certt.h" |
23 | |
24 | SEC_BEGIN_PROTOS |
25 | |
26 | /**************************************************************************** |
27 | * |
28 | * RFC1485 ascii to/from X.? RelativeDistinguishedName (aka CERTName) |
29 | * |
30 | ****************************************************************************/ |
31 | |
32 | /* |
33 | ** Convert an ascii RFC1485 encoded name into its CERTName equivalent. |
34 | */ |
35 | extern CERTName *CERT_AsciiToName(const char *string); |
36 | |
37 | /* |
38 | ** Convert an CERTName into its RFC1485 encoded equivalent. |
39 | ** Returns a string that must be freed with PORT_Free(). |
40 | ** This version produces a string for maximum human readability, |
41 | ** not for strict RFC compliance. |
42 | */ |
43 | extern char *CERT_NameToAscii(CERTName *name); |
44 | |
45 | /* |
46 | ** Convert an CERTName into its RFC1485 encoded equivalent. |
47 | ** Returns a string that must be freed with PORT_Free(). |
48 | ** Caller chooses encoding rules. |
49 | */ |
50 | extern char *CERT_NameToAsciiInvertible(CERTName *name, |
51 | CertStrictnessLevel strict); |
52 | |
53 | extern CERTAVA *CERT_CopyAVA(PLArenaPool *arena, CERTAVA *src); |
54 | |
55 | /* convert an OID to dotted-decimal representation */ |
56 | /* Returns a string that must be freed with PR_smprintf_free(). */ |
57 | extern char *CERT_GetOidString(const SECItem *oid); |
58 | |
59 | /* |
60 | ** Examine an AVA and return the tag that refers to it. The AVA tags are |
61 | ** defined as SEC_OID_AVA*. |
62 | */ |
63 | extern SECOidTag CERT_GetAVATag(CERTAVA *ava); |
64 | |
65 | /* |
66 | ** Compare two AVA's, returning the difference between them. |
67 | */ |
68 | extern SECComparison CERT_CompareAVA(const CERTAVA *a, const CERTAVA *b); |
69 | |
70 | /* |
71 | ** Create an RDN (relative-distinguished-name). The argument list is a |
72 | ** NULL terminated list of AVA's. |
73 | */ |
74 | extern CERTRDN *CERT_CreateRDN(PLArenaPool *arena, CERTAVA *avas, ...); |
75 | |
76 | /* |
77 | ** Make a copy of "src" storing it in "dest". |
78 | */ |
79 | extern SECStatus CERT_CopyRDN(PLArenaPool *arena, CERTRDN *dest, CERTRDN *src); |
80 | |
81 | /* |
82 | ** Add an AVA to an RDN. |
83 | ** "rdn" the RDN to add to |
84 | ** "ava" the AVA to add |
85 | */ |
86 | extern SECStatus CERT_AddAVA(PLArenaPool *arena, CERTRDN *rdn, CERTAVA *ava); |
87 | |
88 | /* |
89 | ** Compare two RDN's, returning the difference between them. |
90 | */ |
91 | extern SECComparison CERT_CompareRDN(const CERTRDN *a, const CERTRDN *b); |
92 | |
93 | /* |
94 | ** Create an X.500 style name using a NULL terminated list of RDN's. |
95 | */ |
96 | extern CERTName *CERT_CreateName(CERTRDN *rdn, ...); |
97 | |
98 | /* |
99 | ** Make a copy of "src" storing it in "dest". Memory is allocated in |
100 | ** "dest" for each of the appropriate sub objects. Memory is not freed in |
101 | ** "dest" before allocation is done (use CERT_DestroyName(dest, PR_FALSE) to |
102 | ** do that). |
103 | */ |
104 | extern SECStatus CERT_CopyName(PLArenaPool *arena, CERTName *dest, |
105 | const CERTName *src); |
106 | |
107 | /* |
108 | ** Destroy a Name object. |
109 | ** "name" the CERTName to destroy |
110 | ** "freeit" if PR_TRUE then free the object as well as its sub-objects |
111 | */ |
112 | extern void CERT_DestroyName(CERTName *name); |
113 | |
114 | /* |
115 | ** Add an RDN to a name. |
116 | ** "name" the name to add the RDN to |
117 | ** "rdn" the RDN to add to name |
118 | */ |
119 | extern SECStatus CERT_AddRDN(CERTName *name, CERTRDN *rdn); |
120 | |
121 | /* |
122 | ** Compare two names, returning the difference between them. |
123 | */ |
124 | extern SECComparison CERT_CompareName(const CERTName *a, const CERTName *b); |
125 | |
126 | /* |
127 | ** Convert a CERTName into something readable |
128 | */ |
129 | extern char *CERT_FormatName(CERTName *name); |
130 | |
131 | /* |
132 | ** Convert a der-encoded integer to a hex printable string form. |
133 | ** Perhaps this should be a SEC function but it's only used for certs. |
134 | */ |
135 | extern char *CERT_Hexify(SECItem *i, int do_colon); |
136 | |
137 | /* |
138 | ** Converts DER string (with explicit length) into zString, if destination |
139 | ** buffer is big enough to receive it. Does quoting and/or escaping as |
140 | ** specified in RFC 1485. Input string must be single or multi-byte DER |
141 | ** character set, (ASCII, UTF8, or ISO 8851-x) not a wide character set. |
142 | ** Returns SECSuccess or SECFailure with error code set. If output buffer |
143 | ** is too small, sets error code SEC_ERROR_OUTPUT_LEN. |
144 | */ |
145 | extern SECStatus CERT_RFC1485_EscapeAndQuote(char *dst, int dstlen, char *src, |
146 | int srclen); |
147 | |
148 | /****************************************************************************** |
149 | * |
150 | * Certificate handling operations |
151 | * |
152 | *****************************************************************************/ |
153 | |
154 | /* |
155 | ** Create a new validity object given two unix time values. |
156 | ** "notBefore" the time before which the validity is not valid |
157 | ** "notAfter" the time after which the validity is not valid |
158 | */ |
159 | extern CERTValidity *CERT_CreateValidity(PRTime notBefore, PRTime notAfter); |
160 | |
161 | /* |
162 | ** Destroy a validity object. |
163 | ** "v" the validity to destroy |
164 | ** "freeit" if PR_TRUE then free the object as well as its sub-objects |
165 | */ |
166 | extern void CERT_DestroyValidity(CERTValidity *v); |
167 | |
168 | /* |
169 | ** Copy the "src" object to "dest". Memory is allocated in "dest" for |
170 | ** each of the appropriate sub-objects. Memory in "dest" is not freed |
171 | ** before memory is allocated (use CERT_DestroyValidity(v, PR_FALSE) to do |
172 | ** that). |
173 | */ |
174 | extern SECStatus CERT_CopyValidity(PLArenaPool *arena, CERTValidity *dest, |
175 | CERTValidity *src); |
176 | |
177 | /* |
178 | ** The cert lib considers a cert or CRL valid if the "notBefore" time is |
179 | ** in the not-too-distant future, e.g. within the next 24 hours. This |
180 | ** prevents freshly issued certificates from being considered invalid |
181 | ** because the local system's time zone is incorrectly set. |
182 | ** The amount of "pending slop time" is adjustable by the application. |
183 | ** Units of SlopTime are seconds. Default is 86400 (24 hours). |
184 | ** Negative SlopTime values are not allowed. |
185 | */ |
186 | PRInt32 CERT_GetSlopTime(void); |
187 | |
188 | SECStatus CERT_SetSlopTime(PRInt32 slop); |
189 | |
190 | /* |
191 | ** Create a new certificate object. The result must be wrapped with an |
192 | ** CERTSignedData to create a signed certificate. |
193 | ** "serialNumber" the serial number |
194 | ** "issuer" the name of the certificate issuer |
195 | ** "validity" the validity period of the certificate |
196 | ** "req" the certificate request that prompted the certificate issuance |
197 | */ |
198 | extern CERTCertificate *CERT_CreateCertificate(unsigned long serialNumber, |
199 | CERTName *issuer, |
200 | CERTValidity *validity, |
201 | CERTCertificateRequest *req); |
202 | |
203 | /* |
204 | ** Destroy a certificate object |
205 | ** "cert" the certificate to destroy |
206 | ** NOTE: certificate's are reference counted. This call decrements the |
207 | ** reference count, and if the result is zero, then the object is destroyed |
208 | ** and optionally freed. |
209 | */ |
210 | extern void CERT_DestroyCertificate(CERTCertificate *cert); |
211 | |
212 | /* |
213 | ** Make a shallow copy of a certificate "c". Just increments the |
214 | ** reference count on "c". |
215 | */ |
216 | extern CERTCertificate *CERT_DupCertificate(CERTCertificate *c); |
217 | |
218 | /* Access the DER of the certificate. This only creates a reference to the DER |
219 | * in the outparam not a copy. To avoid the pointer becoming invalid, use |
220 | * CERT_DupCertificate() and keep a reference to the duplicate alive. |
221 | */ |
222 | extern SECStatus CERT_GetCertificateDer(const CERTCertificate *c, SECItem *der); |
223 | |
224 | /* |
225 | ** Create a new certificate request. This result must be wrapped with an |
226 | ** CERTSignedData to create a signed certificate request. |
227 | ** "name" the subject name (who the certificate request is from) |
228 | ** "spki" describes/defines the public key the certificate is for |
229 | ** "attributes" if non-zero, some optional attribute data |
230 | */ |
231 | extern CERTCertificateRequest *CERT_CreateCertificateRequest( |
232 | CERTName *name, CERTSubjectPublicKeyInfo *spki, SECItem **attributes); |
233 | |
234 | /* |
235 | ** Destroy a certificate-request object |
236 | ** "r" the certificate-request to destroy |
237 | ** "freeit" if PR_TRUE then free the object as well as its sub-objects |
238 | */ |
239 | extern void CERT_DestroyCertificateRequest(CERTCertificateRequest *r); |
240 | |
241 | /* |
242 | ** Start adding extensions to a certificate request. |
243 | */ |
244 | void *CERT_StartCertificateRequestAttributes(CERTCertificateRequest *req); |
245 | |
246 | /* |
247 | ** Reformat the certificate extension list into a CertificateRequest |
248 | ** attribute list. |
249 | */ |
250 | SECStatus CERT_FinishCertificateRequestAttributes(CERTCertificateRequest *req); |
251 | |
252 | /* |
253 | ** Extract the Extension Requests from a DER CertRequest attribute list. |
254 | */ |
255 | SECStatus CERT_GetCertificateRequestExtensions(CERTCertificateRequest *req, |
256 | CERTCertExtension ***exts); |
257 | |
258 | /* |
259 | ** Extract a public key object from a certificate |
260 | */ |
261 | extern SECKEYPublicKey *(CERTCertificate *cert); |
262 | |
263 | /* |
264 | ** Retrieve the Key Type associated with the cert we're dealing with |
265 | */ |
266 | |
267 | extern KeyType CERT_GetCertKeyType(const CERTSubjectPublicKeyInfo *spki); |
268 | |
269 | /* |
270 | ** Initialize the certificate database. This is called to create |
271 | ** the initial list of certificates in the database. |
272 | */ |
273 | extern SECStatus CERT_InitCertDB(CERTCertDBHandle *handle); |
274 | |
275 | extern int CERT_GetDBContentVersion(CERTCertDBHandle *handle); |
276 | |
277 | /* |
278 | ** Default certificate database routines |
279 | */ |
280 | extern void CERT_SetDefaultCertDB(CERTCertDBHandle *handle); |
281 | |
282 | extern CERTCertDBHandle *CERT_GetDefaultCertDB(void); |
283 | |
284 | extern CERTCertList *CERT_GetCertChainFromCert(CERTCertificate *cert, |
285 | PRTime time, SECCertUsage usage); |
286 | extern CERTCertificate *CERT_NewTempCertificate(CERTCertDBHandle *handle, |
287 | SECItem *derCert, |
288 | char *nickname, PRBool isperm, |
289 | PRBool copyDER); |
290 | |
291 | /****************************************************************************** |
292 | * |
293 | * X.500 Name handling operations |
294 | * |
295 | *****************************************************************************/ |
296 | |
297 | /* |
298 | ** Create an AVA (attribute-value-assertion) |
299 | ** "arena" the memory arena to alloc from |
300 | ** "kind" is one of SEC_OID_AVA_* |
301 | ** "valueType" is one of DER_PRINTABLE_STRING, DER_IA5_STRING, or |
302 | ** DER_T61_STRING |
303 | ** "value" is the null terminated string containing the value |
304 | */ |
305 | extern CERTAVA *CERT_CreateAVA(PLArenaPool *arena, SECOidTag kind, |
306 | int valueType, char *value); |
307 | |
308 | /* |
309 | ** Extract the Distinguished Name from a DER encoded certificate |
310 | ** "derCert" is the DER encoded certificate |
311 | ** "derName" is the SECItem that the name is returned in |
312 | */ |
313 | extern SECStatus CERT_NameFromDERCert(SECItem *derCert, SECItem *derName); |
314 | |
315 | /* |
316 | ** Extract the Issuers Distinguished Name from a DER encoded certificate |
317 | ** "derCert" is the DER encoded certificate |
318 | ** "derName" is the SECItem that the name is returned in |
319 | */ |
320 | extern SECStatus CERT_IssuerNameFromDERCert(SECItem *derCert, SECItem *derName); |
321 | |
322 | extern SECItem *CERT_EncodeGeneralName(CERTGeneralName *genName, SECItem *dest, |
323 | PLArenaPool *arena); |
324 | |
325 | extern CERTGeneralName *CERT_DecodeGeneralName(PLArenaPool *reqArena, |
326 | SECItem *encodedName, |
327 | CERTGeneralName *genName); |
328 | |
329 | /* |
330 | ** Generate a database search key for a certificate, based on the |
331 | ** issuer and serial number. |
332 | ** "arena" the memory arena to alloc from |
333 | ** "derCert" the DER encoded certificate |
334 | ** "key" the returned key |
335 | */ |
336 | extern SECStatus CERT_KeyFromDERCert(PLArenaPool *reqArena, SECItem *derCert, |
337 | SECItem *key); |
338 | |
339 | extern SECStatus CERT_KeyFromIssuerAndSN(PLArenaPool *arena, SECItem *issuer, |
340 | SECItem *sn, SECItem *key); |
341 | |
342 | extern SECStatus CERT_SerialNumberFromDERCert(SECItem *derCert, |
343 | SECItem *derName); |
344 | |
345 | /* |
346 | ** Generate a database search key for a crl, based on the |
347 | ** issuer. |
348 | ** "arena" the memory arena to alloc from |
349 | ** "derCrl" the DER encoded crl |
350 | ** "key" the returned key |
351 | */ |
352 | extern SECStatus CERT_KeyFromDERCrl(PLArenaPool *arena, SECItem *derCrl, |
353 | SECItem *key); |
354 | |
355 | /* |
356 | ** Open the certificate database. Use callback to get name of database. |
357 | */ |
358 | extern SECStatus CERT_OpenCertDB(CERTCertDBHandle *handle, PRBool readOnly, |
359 | CERTDBNameFunc namecb, void *cbarg); |
360 | |
361 | /* Open the certificate database. Use given filename for database. */ |
362 | extern SECStatus CERT_OpenCertDBFilename(CERTCertDBHandle *handle, |
363 | char *certdbname, PRBool readOnly); |
364 | |
365 | /* |
366 | ** Open and initialize a cert database that is entirely in memory. This |
367 | ** can be used when the permanent database can not be opened or created. |
368 | */ |
369 | extern SECStatus CERT_OpenVolatileCertDB(CERTCertDBHandle *handle); |
370 | |
371 | /* |
372 | ** Extract the list of host names, host name patters, IP address strings |
373 | ** this cert is valid for. |
374 | ** This function does NOT return nicknames. |
375 | ** Type CERTCertNicknames is being used because it's a convenient |
376 | ** data structure to carry a list of strings and its count. |
377 | */ |
378 | extern CERTCertNicknames *CERT_GetValidDNSPatternsFromCert( |
379 | CERTCertificate *cert); |
380 | |
381 | /* |
382 | ** Check the hostname to make sure that it matches the shexp that |
383 | ** is given in the common name of the certificate. |
384 | */ |
385 | extern SECStatus CERT_VerifyCertName(const CERTCertificate *cert, |
386 | const char *hostname); |
387 | |
388 | /* |
389 | ** Add a domain name to the list of names that the user has explicitly |
390 | ** allowed (despite cert name mismatches) for use with a server cert. |
391 | */ |
392 | extern SECStatus CERT_AddOKDomainName(CERTCertificate *cert, |
393 | const char *hostname); |
394 | |
395 | /* |
396 | ** Decode a DER encoded certificate into an CERTCertificate structure |
397 | ** "derSignedCert" is the DER encoded signed certificate |
398 | ** "copyDER" is true if the DER should be copied, false if the |
399 | ** existing copy should be referenced |
400 | ** "nickname" is the nickname to use in the database. If it is NULL |
401 | ** then a temporary nickname is generated. |
402 | */ |
403 | extern CERTCertificate *CERT_DecodeDERCertificate(SECItem *derSignedCert, |
404 | PRBool copyDER, |
405 | char *nickname); |
406 | /* |
407 | ** Decode a DER encoded CRL into a CERTSignedCrl structure |
408 | ** "derSignedCrl" is the DER encoded signed CRL. |
409 | ** "type" must be SEC_CRL_TYPE. |
410 | */ |
411 | #define SEC_CRL_TYPE 1 |
412 | #define SEC_KRL_TYPE 0 /* deprecated */ |
413 | |
414 | extern CERTSignedCrl *CERT_DecodeDERCrl(PLArenaPool *arena, |
415 | SECItem *derSignedCrl, int type); |
416 | |
417 | /* |
418 | * same as CERT_DecodeDERCrl, plus allow options to be passed in |
419 | */ |
420 | |
421 | extern CERTSignedCrl *CERT_DecodeDERCrlWithFlags(PLArenaPool *narena, |
422 | SECItem *derSignedCrl, |
423 | int type, PRInt32 options); |
424 | |
425 | /* CRL options to pass */ |
426 | |
427 | #define CRL_DECODE_DEFAULT_OPTIONS 0x00000000 |
428 | |
429 | /* when CRL_DECODE_DONT_COPY_DER is set, the DER is not copied . The |
430 | application must then keep derSignedCrl until it destroys the |
431 | CRL . Ideally, it should allocate derSignedCrl in an arena |
432 | and pass that arena in as the first argument to |
433 | CERT_DecodeDERCrlWithFlags */ |
434 | |
435 | #define CRL_DECODE_DONT_COPY_DER 0x00000001 |
436 | #define CRL_DECODE_SKIP_ENTRIES 0x00000002 |
437 | #define CRL_DECODE_KEEP_BAD_CRL 0x00000004 |
438 | #define CRL_DECODE_ADOPT_HEAP_DER 0x00000008 |
439 | |
440 | /* complete the decoding of a partially decoded CRL, ie. decode the |
441 | entries. Note that entries is an optional field in a CRL, so the |
442 | "entries" pointer in CERTCrlStr may still be NULL even after |
443 | function returns SECSuccess */ |
444 | |
445 | extern SECStatus CERT_CompleteCRLDecodeEntries(CERTSignedCrl *crl); |
446 | |
447 | /* Validate CRL then import it to the dbase. If there is already a CRL with the |
448 | * same CA in the dbase, it will be replaced if derCRL is more up to date. |
449 | * If the process successes, a CRL will be returned. Otherwise, a NULL will |
450 | * be returned. The caller should call PORT_GetError() for the exactly error |
451 | * code. |
452 | */ |
453 | extern CERTSignedCrl *CERT_ImportCRL(CERTCertDBHandle *handle, SECItem *derCRL, |
454 | char *url, int type, void *wincx); |
455 | |
456 | extern void CERT_DestroyCrl(CERTSignedCrl *crl); |
457 | |
458 | /* this is a hint to flush the CRL cache. crlKey is the DER subject of |
459 | the issuer (CA). */ |
460 | void CERT_CRLCacheRefreshIssuer(CERTCertDBHandle *dbhandle, SECItem *crlKey); |
461 | |
462 | /* add the specified DER CRL object to the CRL cache. Doing so will allow |
463 | certificate verification functions (such as CERT_VerifyCertificate) |
464 | to automatically find and make use of this CRL object. |
465 | Once a CRL is added to the CRL cache, the application must hold on to |
466 | the object's memory, because the cache will reference it directly. The |
467 | application can only free the object after it calls CERT_UncacheCRL to |
468 | remove it from the CRL cache. |
469 | */ |
470 | SECStatus CERT_CacheCRL(CERTCertDBHandle *dbhandle, SECItem *newcrl); |
471 | |
472 | /* remove a previously added CRL object from the CRL cache. It is OK |
473 | for the application to free the memory after a successful removal |
474 | */ |
475 | SECStatus CERT_UncacheCRL(CERTCertDBHandle *dbhandle, SECItem *oldcrl); |
476 | |
477 | /* |
478 | ** Find a certificate in the database |
479 | ** "key" is the database key to look for |
480 | */ |
481 | extern CERTCertificate *CERT_FindCertByKey(CERTCertDBHandle *handle, |
482 | SECItem *key); |
483 | |
484 | /* |
485 | ** Find a certificate in the database by name |
486 | ** "name" is the distinguished name to look up |
487 | */ |
488 | extern CERTCertificate *CERT_FindCertByName(CERTCertDBHandle *handle, |
489 | SECItem *name); |
490 | |
491 | /* |
492 | ** Find a certificate in the database by name |
493 | ** "name" is the distinguished name to look up (in ascii) |
494 | */ |
495 | extern CERTCertificate *CERT_FindCertByNameString(CERTCertDBHandle *handle, |
496 | char *name); |
497 | |
498 | /* |
499 | ** Find a certificate in the database by name and keyid |
500 | ** "name" is the distinguished name to look up |
501 | ** "keyID" is the value of the subjectKeyID to match |
502 | */ |
503 | extern CERTCertificate *CERT_FindCertByKeyID(CERTCertDBHandle *handle, |
504 | SECItem *name, SECItem *keyID); |
505 | |
506 | /* |
507 | ** Generate a certificate key from the issuer and serialnumber, then look it |
508 | ** up in the database. Return the cert if found. |
509 | ** "issuerAndSN" is the issuer and serial number to look for |
510 | */ |
511 | extern CERTCertificate *CERT_FindCertByIssuerAndSN( |
512 | CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN); |
513 | extern CERTCertificate *CERT_FindCertByIssuerAndSNCX( |
514 | CERTCertDBHandle *handle, CERTIssuerAndSN *issuerAndSN, void *wincx); |
515 | |
516 | /* |
517 | ** Find a certificate in the database by a subject key ID |
518 | ** "subjKeyID" is the subject Key ID to look for |
519 | */ |
520 | extern CERTCertificate *CERT_FindCertBySubjectKeyID(CERTCertDBHandle *handle, |
521 | SECItem *subjKeyID); |
522 | |
523 | /* |
524 | ** Encode Certificate SKID (Subject Key ID) extension. |
525 | ** |
526 | */ |
527 | extern SECStatus CERT_EncodeSubjectKeyID(PLArenaPool *arena, |
528 | const SECItem *srcString, |
529 | SECItem *encodedValue); |
530 | |
531 | /* |
532 | ** Find a certificate in the database by a nickname |
533 | ** "nickname" is the ascii string nickname to look for |
534 | */ |
535 | extern CERTCertificate *CERT_FindCertByNickname(CERTCertDBHandle *handle, |
536 | const char *nickname); |
537 | |
538 | /* |
539 | ** Find a certificate in the database by a DER encoded certificate |
540 | ** "derCert" is the DER encoded certificate |
541 | */ |
542 | extern CERTCertificate *CERT_FindCertByDERCert(CERTCertDBHandle *handle, |
543 | SECItem *derCert); |
544 | |
545 | /* |
546 | ** Find a certificate in the database by a email address |
547 | ** "emailAddr" is the email address to look up |
548 | */ |
549 | CERTCertificate *CERT_FindCertByEmailAddr(CERTCertDBHandle *handle, |
550 | char *emailAddr); |
551 | |
552 | /* |
553 | ** Find a certificate in the database by a email address or nickname |
554 | ** "name" is the email address or nickname to look up |
555 | */ |
556 | CERTCertificate *CERT_FindCertByNicknameOrEmailAddr(CERTCertDBHandle *handle, |
557 | const char *name); |
558 | CERTCertificate *CERT_FindCertByNicknameOrEmailAddrCX(CERTCertDBHandle *handle, |
559 | const char *name, |
560 | void *wincx); |
561 | |
562 | /* |
563 | ** Find a certificate in the database by a email address or nickname |
564 | ** and require it to have the given usage. |
565 | ** "name" is the email address or nickname to look up |
566 | */ |
567 | CERTCertificate *CERT_FindCertByNicknameOrEmailAddrForUsage( |
568 | CERTCertDBHandle *handle, const char *name, SECCertUsage lookingForUsage); |
569 | CERTCertificate *CERT_FindCertByNicknameOrEmailAddrForUsageCX( |
570 | CERTCertDBHandle *handle, const char *name, SECCertUsage lookingForUsage, |
571 | void *wincx); |
572 | |
573 | /* |
574 | ** Find a certificate in the database by a digest of a subject public key |
575 | ** "spkDigest" is the digest to look up |
576 | */ |
577 | extern CERTCertificate *CERT_FindCertBySPKDigest(CERTCertDBHandle *handle, |
578 | SECItem *spkDigest); |
579 | |
580 | /* |
581 | * Find the issuer of a cert |
582 | */ |
583 | CERTCertificate *CERT_FindCertIssuer(CERTCertificate *cert, PRTime validTime, |
584 | SECCertUsage usage); |
585 | |
586 | /* |
587 | ** Check the validity times of a certificate vs. time 't', allowing |
588 | ** some slop for broken clocks and stuff. |
589 | ** "cert" is the certificate to be checked |
590 | ** "t" is the time to check against |
591 | ** "allowOverride" if true then check to see if the invalidity has |
592 | ** been overridden by the user. |
593 | */ |
594 | extern SECCertTimeValidity CERT_CheckCertValidTimes(const CERTCertificate *cert, |
595 | PRTime t, |
596 | PRBool allowOverride); |
597 | |
598 | /* |
599 | ** WARNING - this function is deprecated, and will either go away or have |
600 | ** a new API in the near future. |
601 | ** |
602 | ** Check the validity times of a certificate vs. the current time, allowing |
603 | ** some slop for broken clocks and stuff. |
604 | ** "cert" is the certificate to be checked |
605 | */ |
606 | extern SECStatus CERT_CertTimesValid(CERTCertificate *cert); |
607 | |
608 | /* |
609 | ** Extract the validity times from a certificate |
610 | ** "c" is the certificate |
611 | ** "notBefore" is the start of the validity period |
612 | ** "notAfter" is the end of the validity period |
613 | */ |
614 | extern SECStatus CERT_GetCertTimes(const CERTCertificate *c, PRTime *notBefore, |
615 | PRTime *notAfter); |
616 | |
617 | /* |
618 | ** Extract the issuer and serial number from a certificate |
619 | */ |
620 | extern CERTIssuerAndSN *CERT_GetCertIssuerAndSN(PLArenaPool *, |
621 | CERTCertificate *); |
622 | |
623 | /* |
624 | ** verify the signature of a signed data object with a given certificate |
625 | ** "sd" the signed data object to be verified |
626 | ** "cert" the certificate to use to check the signature |
627 | */ |
628 | extern SECStatus CERT_VerifySignedData(CERTSignedData *sd, |
629 | CERTCertificate *cert, PRTime t, |
630 | void *wincx); |
631 | /* |
632 | ** verify the signature of a signed data object with the given DER publickey |
633 | */ |
634 | extern SECStatus CERT_VerifySignedDataWithPublicKeyInfo( |
635 | CERTSignedData *sd, CERTSubjectPublicKeyInfo *pubKeyInfo, void *wincx); |
636 | |
637 | /* |
638 | ** verify the signature of a signed data object with a SECKEYPublicKey. |
639 | */ |
640 | extern SECStatus CERT_VerifySignedDataWithPublicKey(const CERTSignedData *sd, |
641 | SECKEYPublicKey *pubKey, |
642 | void *wincx); |
643 | |
644 | /* |
645 | ** NEW FUNCTIONS with new bit-field-FIELD SECCertificateUsage - please use |
646 | ** verify a certificate by checking validity times against a certain time, |
647 | ** that we trust the issuer, and that the signature on the certificate is |
648 | ** valid. |
649 | ** "cert" the certificate to verify |
650 | ** "checkSig" only check signatures if true |
651 | */ |
652 | extern SECStatus CERT_VerifyCertificate(CERTCertDBHandle *handle, |
653 | CERTCertificate *cert, PRBool checkSig, |
654 | SECCertificateUsage requiredUsages, |
655 | PRTime t, void *wincx, |
656 | CERTVerifyLog *log, |
657 | SECCertificateUsage *returnedUsages); |
658 | |
659 | /* same as above, but uses current time */ |
660 | extern SECStatus CERT_VerifyCertificateNow(CERTCertDBHandle *handle, |
661 | CERTCertificate *cert, |
662 | PRBool checkSig, |
663 | SECCertificateUsage requiredUsages, |
664 | void *wincx, |
665 | SECCertificateUsage *returnedUsages); |
666 | |
667 | /* |
668 | ** Verify that a CA cert can certify some (unspecified) leaf cert for a given |
669 | ** purpose. This is used by UI code to help identify where a chain may be |
670 | ** broken and why. This takes identical parameters to CERT_VerifyCert |
671 | */ |
672 | extern SECStatus CERT_VerifyCACertForUsage(CERTCertDBHandle *handle, |
673 | CERTCertificate *cert, |
674 | PRBool checkSig, |
675 | SECCertUsage certUsage, PRTime t, |
676 | void *wincx, CERTVerifyLog *log); |
677 | |
678 | /* |
679 | ** OLD OBSOLETE FUNCTIONS with enum SECCertUsage - DO NOT USE FOR NEW CODE |
680 | ** verify a certificate by checking validity times against a certain time, |
681 | ** that we trust the issuer, and that the signature on the certificate is |
682 | ** valid. |
683 | ** "cert" the certificate to verify |
684 | ** "checkSig" only check signatures if true |
685 | */ |
686 | extern SECStatus CERT_VerifyCert(CERTCertDBHandle *handle, |
687 | CERTCertificate *cert, PRBool checkSig, |
688 | SECCertUsage certUsage, PRTime t, void *wincx, |
689 | CERTVerifyLog *log); |
690 | |
691 | /* same as above, but uses current time */ |
692 | extern SECStatus CERT_VerifyCertNow(CERTCertDBHandle *handle, |
693 | CERTCertificate *cert, PRBool checkSig, |
694 | SECCertUsage certUsage, void *wincx); |
695 | |
696 | SECStatus CERT_VerifyCertChain(CERTCertDBHandle *handle, CERTCertificate *cert, |
697 | PRBool checkSig, SECCertUsage certUsage, |
698 | PRTime t, void *wincx, CERTVerifyLog *log); |
699 | |
700 | /* |
701 | ** Read a base64 ascii encoded DER certificate and convert it to our |
702 | ** internal format. |
703 | ** "certstr" is a null-terminated string containing the certificate |
704 | */ |
705 | extern CERTCertificate *CERT_ConvertAndDecodeCertificate(char *certstr); |
706 | |
707 | /* |
708 | ** Read a certificate in some foreign format, and convert it to our |
709 | ** internal format. |
710 | ** "certbuf" is the buffer containing the certificate |
711 | ** "certlen" is the length of the buffer |
712 | ** NOTE - currently supports netscape base64 ascii encoded raw certs |
713 | ** and netscape binary DER typed files. |
714 | */ |
715 | extern CERTCertificate *CERT_DecodeCertFromPackage(char *certbuf, int certlen); |
716 | |
717 | extern SECStatus CERT_ImportCAChain(SECItem *certs, int numcerts, |
718 | SECCertUsage certUsage); |
719 | |
720 | extern SECStatus CERT_ImportCAChainTrusted(SECItem *certs, int numcerts, |
721 | SECCertUsage certUsage); |
722 | |
723 | /* |
724 | ** Read a certificate chain in some foreign format, and pass it to a |
725 | ** callback function. |
726 | ** "certbuf" is the buffer containing the certificate |
727 | ** "certlen" is the length of the buffer |
728 | ** "f" is the callback function |
729 | ** "arg" is the callback argument |
730 | */ |
731 | typedef SECStatus(PR_CALLBACK *CERTImportCertificateFunc)(void *arg, |
732 | SECItem **certs, |
733 | int numcerts); |
734 | |
735 | extern SECStatus CERT_DecodeCertPackage(char *certbuf, int certlen, |
736 | CERTImportCertificateFunc f, void *arg); |
737 | |
738 | /* |
739 | ** Returns the value of an AVA. This was a formerly static |
740 | ** function that has been exposed due to the need to decode |
741 | ** and convert unicode strings to UTF8. |
742 | ** |
743 | ** XXX This function resides in certhtml.c, should it be |
744 | ** moved elsewhere? |
745 | */ |
746 | extern SECItem *CERT_DecodeAVAValue(const SECItem *derAVAValue); |
747 | |
748 | /* |
749 | ** extract various element strings from a distinguished name. |
750 | ** "name" the distinguished name |
751 | */ |
752 | |
753 | extern char *CERT_GetCertificateEmailAddress(CERTCertificate *cert); |
754 | |
755 | extern char *CERT_GetCertEmailAddress(const CERTName *name); |
756 | |
757 | extern const char *CERT_GetFirstEmailAddress(CERTCertificate *cert); |
758 | |
759 | extern const char *CERT_GetNextEmailAddress(CERTCertificate *cert, |
760 | const char *prev); |
761 | |
762 | /* The return value must be freed with PORT_Free. */ |
763 | extern char *CERT_GetCommonName(const CERTName *name); |
764 | |
765 | extern char *CERT_GetCountryName(const CERTName *name); |
766 | |
767 | extern char *CERT_GetLocalityName(const CERTName *name); |
768 | |
769 | extern char *CERT_GetStateName(const CERTName *name); |
770 | |
771 | extern char *CERT_GetOrgName(const CERTName *name); |
772 | |
773 | extern char *CERT_GetOrgUnitName(const CERTName *name); |
774 | |
775 | extern char *CERT_GetDomainComponentName(const CERTName *name); |
776 | |
777 | extern char *CERT_GetCertUid(const CERTName *name); |
778 | |
779 | /* manipulate the trust parameters of a certificate */ |
780 | |
781 | extern SECStatus CERT_GetCertTrust(const CERTCertificate *cert, |
782 | CERTCertTrust *trust); |
783 | |
784 | extern SECStatus CERT_ChangeCertTrust(CERTCertDBHandle *handle, |
785 | CERTCertificate *cert, |
786 | CERTCertTrust *trust); |
787 | |
788 | extern SECStatus CERT_ChangeCertTrustByUsage(CERTCertDBHandle *certdb, |
789 | CERTCertificate *cert, |
790 | SECCertUsage usage); |
791 | |
792 | /************************************************************************* |
793 | * |
794 | * manipulate the extensions of a certificate |
795 | * |
796 | ************************************************************************/ |
797 | |
798 | /* |
799 | ** Set up a cert for adding X509v3 extensions. Returns an opaque handle |
800 | ** used by the next two routines. |
801 | ** "cert" is the certificate we are adding extensions to |
802 | */ |
803 | extern void *CERT_StartCertExtensions(CERTCertificate *cert); |
804 | |
805 | /* |
806 | ** Add an extension to a certificate. |
807 | ** "exthandle" is the handle returned by the previous function |
808 | ** "idtag" is the integer tag for the OID that should ID this extension |
809 | ** "value" is the value of the extension |
810 | ** "critical" is the critical extension flag |
811 | ** "copyData" is a flag indicating whether the value data should be |
812 | ** copied. |
813 | */ |
814 | extern SECStatus CERT_AddExtension(void *exthandle, int idtag, SECItem *value, |
815 | PRBool critical, PRBool copyData); |
816 | |
817 | extern SECStatus CERT_AddExtensionByOID(void *exthandle, SECItem *oid, |
818 | SECItem *value, PRBool critical, |
819 | PRBool copyData); |
820 | |
821 | extern SECStatus CERT_EncodeAndAddExtension(void *exthandle, int idtag, |
822 | void *value, PRBool critical, |
823 | const SEC_ASN1Template *atemplate); |
824 | |
825 | extern SECStatus CERT_EncodeAndAddBitStrExtension(void *exthandle, int idtag, |
826 | SECItem *value, |
827 | PRBool critical); |
828 | |
829 | extern SECStatus CERT_EncodeAltNameExtension(PLArenaPool *arena, |
830 | CERTGeneralName *value, |
831 | SECItem *encodedValue); |
832 | |
833 | /* |
834 | ** Finish adding cert extensions. Does final processing on extension |
835 | ** data, putting it in the right format, and freeing any temporary |
836 | ** storage. |
837 | ** "exthandle" is the handle used to add extensions to a certificate |
838 | */ |
839 | extern SECStatus CERT_FinishExtensions(void *exthandle); |
840 | |
841 | /* |
842 | ** Merge an external list of extensions into a cert's extension list, adding one |
843 | ** only when its OID matches none of the cert's existing extensions. Call this |
844 | ** immediately before calling CERT_FinishExtensions(). |
845 | */ |
846 | SECStatus CERT_MergeExtensions(void *exthandle, CERTCertExtension **exts); |
847 | |
848 | /* If the extension is found, return its criticality and value. |
849 | ** This allocate storage for the returning extension value. |
850 | */ |
851 | extern SECStatus CERT_GetExtenCriticality(CERTCertExtension **extensions, |
852 | int tag, PRBool *isCritical); |
853 | |
854 | extern void CERT_DestroyOidSequence(CERTOidSequence *oidSeq); |
855 | |
856 | /**************************************************************************** |
857 | * |
858 | * DER encode and decode extension values |
859 | * |
860 | ****************************************************************************/ |
861 | |
862 | /* Encode the value of the basicConstraint extension. |
863 | ** arena - where to allocate memory for the encoded value. |
864 | ** value - extension value to encode |
865 | ** encodedValue - output encoded value |
866 | */ |
867 | extern SECStatus CERT_EncodeBasicConstraintValue(PLArenaPool *arena, |
868 | CERTBasicConstraints *value, |
869 | SECItem *encodedValue); |
870 | |
871 | /* |
872 | ** Encode the value of the authorityKeyIdentifier extension. |
873 | */ |
874 | extern SECStatus CERT_EncodeAuthKeyID(PLArenaPool *arena, CERTAuthKeyID *value, |
875 | SECItem *encodedValue); |
876 | |
877 | /* |
878 | ** Encode the value of the crlDistributionPoints extension. |
879 | */ |
880 | extern SECStatus CERT_EncodeCRLDistributionPoints( |
881 | PLArenaPool *arena, CERTCrlDistributionPoints *value, SECItem *derValue); |
882 | |
883 | /* |
884 | ** Decodes a DER encoded basicConstaint extension value into a readable format |
885 | ** value - decoded value |
886 | ** encodedValue - value to decoded |
887 | */ |
888 | extern SECStatus CERT_DecodeBasicConstraintValue(CERTBasicConstraints *value, |
889 | const SECItem *encodedValue); |
890 | |
891 | /* Decodes a DER encoded authorityKeyIdentifier extension value into a |
892 | ** readable format. |
893 | ** arena - where to allocate memory for the decoded value |
894 | ** encodedValue - value to be decoded |
895 | ** Returns a CERTAuthKeyID structure which contains the decoded value |
896 | */ |
897 | extern CERTAuthKeyID *CERT_DecodeAuthKeyID(PLArenaPool *arena, |
898 | const SECItem *encodedValue); |
899 | |
900 | /* Decodes a DER encoded crlDistributionPoints extension value into a |
901 | ** readable format. |
902 | ** arena - where to allocate memory for the decoded value |
903 | ** der - value to be decoded |
904 | ** Returns a CERTCrlDistributionPoints structure which contains the |
905 | ** decoded value |
906 | */ |
907 | extern CERTCrlDistributionPoints *CERT_DecodeCRLDistributionPoints( |
908 | PLArenaPool *arena, SECItem *der); |
909 | |
910 | /* Extract certain name type from a generalName */ |
911 | extern void *CERT_GetGeneralNameByType(CERTGeneralName *genNames, |
912 | CERTGeneralNameType type, |
913 | PRBool derFormat); |
914 | |
915 | extern CERTOidSequence *CERT_DecodeOidSequence(const SECItem *seqItem); |
916 | |
917 | /**************************************************************************** |
918 | * |
919 | * Find extension values of a certificate |
920 | * |
921 | ***************************************************************************/ |
922 | |
923 | extern SECStatus CERT_FindCertExtension(const CERTCertificate *cert, int tag, |
924 | SECItem *value); |
925 | |
926 | extern SECStatus CERT_FindNSCertTypeExtension(CERTCertificate *cert, |
927 | SECItem *value); |
928 | |
929 | extern char *CERT_FindNSStringExtension(CERTCertificate *cert, int oidtag); |
930 | |
931 | extern SECStatus CERT_FindCertExtensionByOID(CERTCertificate *cert, |
932 | SECItem *oid, SECItem *value); |
933 | |
934 | /* Returns the decoded value of the authKeyID extension. |
935 | ** Note that this uses passed in the arena to allocate storage for the result |
936 | */ |
937 | extern CERTAuthKeyID *CERT_FindAuthKeyIDExten(PLArenaPool *arena, |
938 | CERTCertificate *cert); |
939 | |
940 | /* Returns the decoded value of the basicConstraint extension. |
941 | */ |
942 | extern SECStatus CERT_FindBasicConstraintExten(CERTCertificate *cert, |
943 | CERTBasicConstraints *value); |
944 | |
945 | /* Returns the decoded value of the crlDistributionPoints extension. |
946 | ** Note that the arena in cert is used to allocate storage for the result |
947 | */ |
948 | extern CERTCrlDistributionPoints *CERT_FindCRLDistributionPoints( |
949 | CERTCertificate *cert); |
950 | |
951 | /* Returns value of the keyUsage extension. This uses PR_Alloc to allocate |
952 | ** buffer for the decoded value. The caller should free up the storage |
953 | ** allocated in value->data. |
954 | */ |
955 | extern SECStatus CERT_FindKeyUsageExtension(CERTCertificate *cert, |
956 | SECItem *value); |
957 | |
958 | /* Return the decoded value of the subjectKeyID extension. The caller should |
959 | ** free up the storage allocated in retItem->data. |
960 | */ |
961 | extern SECStatus CERT_FindSubjectKeyIDExtension(CERTCertificate *cert, |
962 | SECItem *retItem); |
963 | |
964 | /* |
965 | ** If cert is a v3 certificate, and a critical keyUsage extension is included, |
966 | ** then check the usage against the extension value. If a non-critical |
967 | ** keyUsage extension is included, this will return SECSuccess without |
968 | ** checking, since the extension is an advisory field, not a restriction. |
969 | ** If cert is not a v3 certificate, this will return SECSuccess. |
970 | ** cert - certificate |
971 | ** usage - one of the x.509 v3 the Key Usage Extension flags |
972 | */ |
973 | extern SECStatus CERT_CheckCertUsage(CERTCertificate *cert, |
974 | unsigned char usage); |
975 | |
976 | /**************************************************************************** |
977 | * |
978 | * CRL v2 Extensions supported routines |
979 | * |
980 | ****************************************************************************/ |
981 | |
982 | extern SECStatus CERT_FindCRLExtensionByOID(CERTCrl *crl, SECItem *oid, |
983 | SECItem *value); |
984 | |
985 | extern SECStatus CERT_FindCRLExtension(CERTCrl *crl, int tag, SECItem *value); |
986 | |
987 | extern SECStatus CERT_FindInvalidDateExten(CERTCrl *crl, PRTime *value); |
988 | |
989 | /* |
990 | ** Set up a crl for adding X509v3 extensions. Returns an opaque handle |
991 | ** used by routines that take an exthandle (void*) argument . |
992 | ** "crl" is the CRL we are adding extensions to |
993 | */ |
994 | extern void *CERT_StartCRLExtensions(CERTCrl *crl); |
995 | |
996 | /* |
997 | ** Set up a crl entry for adding X509v3 extensions. Returns an opaque handle |
998 | ** used by routines that take an exthandle (void*) argument . |
999 | ** "crl" is the crl we are adding certs entries to |
1000 | ** "entry" is the crl entry we are adding extensions to |
1001 | */ |
1002 | extern void *CERT_StartCRLEntryExtensions(CERTCrl *crl, CERTCrlEntry *entry); |
1003 | |
1004 | extern CERTCertNicknames *CERT_GetCertNicknames(CERTCertDBHandle *handle, |
1005 | int what, void *wincx); |
1006 | |
1007 | /* |
1008 | ** Finds the crlNumber extension and decodes its value into 'value' |
1009 | */ |
1010 | extern SECStatus CERT_FindCRLNumberExten(PLArenaPool *arena, CERTCrl *crl, |
1011 | SECItem *value); |
1012 | |
1013 | extern SECStatus CERT_FindCRLEntryReasonExten(CERTCrlEntry *crlEntry, |
1014 | CERTCRLEntryReasonCode *value); |
1015 | |
1016 | extern void CERT_FreeNicknames(CERTCertNicknames *nicknames); |
1017 | |
1018 | extern PRBool CERT_CompareCerts(const CERTCertificate *c1, |
1019 | const CERTCertificate *c2); |
1020 | |
1021 | extern PRBool CERT_CompareCertsForRedirection(CERTCertificate *c1, |
1022 | CERTCertificate *c2); |
1023 | |
1024 | /* |
1025 | ** Generate an array of the Distinguished Names that the given cert database |
1026 | ** "trusts" |
1027 | */ |
1028 | extern CERTDistNames *CERT_GetSSLCACerts(CERTCertDBHandle *handle); |
1029 | |
1030 | extern void CERT_FreeDistNames(CERTDistNames *names); |
1031 | |
1032 | /* Duplicate distinguished name array */ |
1033 | extern CERTDistNames *CERT_DupDistNames(CERTDistNames *orig); |
1034 | |
1035 | /* |
1036 | ** Generate an array of Distinguished names from an array of nicknames |
1037 | */ |
1038 | extern CERTDistNames *CERT_DistNamesFromNicknames(CERTCertDBHandle *handle, |
1039 | char **nicknames, int nnames); |
1040 | |
1041 | /* |
1042 | ** Generate an array of Distinguished names from a list of certs. |
1043 | */ |
1044 | extern CERTDistNames *CERT_DistNamesFromCertList(CERTCertList *list); |
1045 | |
1046 | /* |
1047 | ** Generate a certificate chain from a certificate. |
1048 | */ |
1049 | extern CERTCertificateList *CERT_CertChainFromCert(CERTCertificate *cert, |
1050 | SECCertUsage usage, |
1051 | PRBool includeRoot); |
1052 | |
1053 | extern CERTCertificateList *CERT_CertListFromCert(CERTCertificate *cert); |
1054 | |
1055 | extern CERTCertificateList *CERT_DupCertList( |
1056 | const CERTCertificateList *oldList); |
1057 | |
1058 | extern void CERT_DestroyCertificateList(CERTCertificateList *list); |
1059 | |
1060 | /* |
1061 | ** is cert a user cert? i.e. does it have CERTDB_USER trust, |
1062 | ** i.e. a private key? |
1063 | */ |
1064 | PRBool CERT_IsUserCert(CERTCertificate *cert); |
1065 | |
1066 | /* is cert a newer than cert b? */ |
1067 | PRBool CERT_IsNewer(CERTCertificate *certa, CERTCertificate *certb); |
1068 | |
1069 | /* currently a stub for address book */ |
1070 | PRBool CERT_IsCertRevoked(CERTCertificate *cert); |
1071 | |
1072 | void CERT_DestroyCertArray(CERTCertificate **certs, unsigned int ncerts); |
1073 | |
1074 | /* convert an email address to lower case */ |
1075 | char *CERT_FixupEmailAddr(const char *emailAddr); |
1076 | |
1077 | /* decode string representation of trust flags into trust struct */ |
1078 | SECStatus CERT_DecodeTrustString(CERTCertTrust *trust, const char *trusts); |
1079 | |
1080 | /* encode trust struct into string representation of trust flags */ |
1081 | char *CERT_EncodeTrustString(CERTCertTrust *trust); |
1082 | |
1083 | /* find the next or prev cert in a subject list */ |
1084 | CERTCertificate *CERT_PrevSubjectCert(CERTCertificate *cert); |
1085 | CERTCertificate *CERT_NextSubjectCert(CERTCertificate *cert); |
1086 | |
1087 | /* |
1088 | * import a collection of certs into the temporary or permanent cert |
1089 | * database |
1090 | */ |
1091 | SECStatus CERT_ImportCerts(CERTCertDBHandle *certdb, SECCertUsage usage, |
1092 | unsigned int ncerts, SECItem **derCerts, |
1093 | CERTCertificate ***retCerts, PRBool keepCerts, |
1094 | PRBool caOnly, char *nickname); |
1095 | |
1096 | char *CERT_MakeCANickname(CERTCertificate *cert); |
1097 | |
1098 | PRBool CERT_IsCACert(CERTCertificate *cert, unsigned int *rettype); |
1099 | |
1100 | PRBool CERT_IsCADERCert(SECItem *derCert, unsigned int *rettype); |
1101 | |
1102 | PRBool CERT_IsRootDERCert(SECItem *derCert); |
1103 | |
1104 | SECStatus CERT_SaveSMimeProfile(CERTCertificate *cert, SECItem *emailProfile, |
1105 | SECItem *profileTime); |
1106 | |
1107 | /* |
1108 | * find the smime symmetric capabilities profile for a given cert |
1109 | */ |
1110 | SECItem *CERT_FindSMimeProfile(CERTCertificate *cert); |
1111 | |
1112 | SECStatus CERT_AddNewCerts(CERTCertDBHandle *handle); |
1113 | |
1114 | CERTCertificatePolicies *CERT_DecodeCertificatePoliciesExtension( |
1115 | const SECItem *extnValue); |
1116 | |
1117 | void CERT_DestroyCertificatePoliciesExtension( |
1118 | CERTCertificatePolicies *policies); |
1119 | |
1120 | CERTCertificatePolicyMappings *CERT_DecodePolicyMappingsExtension( |
1121 | SECItem *encodedCertPolicyMaps); |
1122 | |
1123 | SECStatus CERT_DestroyPolicyMappingsExtension( |
1124 | CERTCertificatePolicyMappings *mappings); |
1125 | |
1126 | SECStatus CERT_DecodePolicyConstraintsExtension( |
1127 | CERTCertificatePolicyConstraints *decodedValue, |
1128 | const SECItem *encodedValue); |
1129 | |
1130 | SECStatus CERT_DecodeInhibitAnyExtension( |
1131 | CERTCertificateInhibitAny *decodedValue, SECItem *extnValue); |
1132 | |
1133 | CERTUserNotice *CERT_DecodeUserNotice(SECItem *noticeItem); |
1134 | |
1135 | extern CERTGeneralName *CERT_DecodeAltNameExtension(PLArenaPool *reqArena, |
1136 | SECItem *EncodedAltName); |
1137 | |
1138 | extern CERTNameConstraints *CERT_DecodeNameConstraintsExtension( |
1139 | PLArenaPool *arena, const SECItem *encodedConstraints); |
1140 | |
1141 | /* returns addr of a NULL termainated array of pointers to CERTAuthInfoAccess */ |
1142 | extern CERTAuthInfoAccess **CERT_DecodeAuthInfoAccessExtension( |
1143 | PLArenaPool *reqArena, const SECItem *encodedExtension); |
1144 | |
1145 | extern CERTPrivKeyUsagePeriod *CERT_DecodePrivKeyUsagePeriodExtension( |
1146 | PLArenaPool *arena, SECItem *extnValue); |
1147 | |
1148 | extern CERTGeneralName *CERT_GetNextGeneralName(CERTGeneralName *current); |
1149 | |
1150 | extern CERTGeneralName *CERT_GetPrevGeneralName(CERTGeneralName *current); |
1151 | |
1152 | /* |
1153 | * Look up name constraints for some certs that do not include name constraints |
1154 | * (Most importantly, root certificates) |
1155 | * |
1156 | * If a matching subject is found, |extensions| will be populated with a copy of |
1157 | * the |
1158 | * DER-encoded name constraints extension. The data in |extensions| will point |
1159 | * to |
1160 | * memory that the caller owns. |
1161 | * |
1162 | * There is no mechanism to configure imposed name constraints right now. All |
1163 | * imposed name constraints are built into NSS. |
1164 | */ |
1165 | SECStatus CERT_GetImposedNameConstraints(const SECItem *derSubject, |
1166 | SECItem *extensions); |
1167 | |
1168 | CERTNameConstraint *CERT_GetNextNameConstraint(CERTNameConstraint *current); |
1169 | |
1170 | CERTNameConstraint *CERT_GetPrevNameConstraint(CERTNameConstraint *current); |
1171 | |
1172 | void CERT_DestroyUserNotice(CERTUserNotice *userNotice); |
1173 | |
1174 | typedef char *(*CERTPolicyStringCallback)(char *org, unsigned long noticeNumber, |
1175 | void *arg); |
1176 | void CERT_SetCAPolicyStringCallback(CERTPolicyStringCallback cb, void *cbarg); |
1177 | |
1178 | char *(CERTCertificate *cert); |
1179 | |
1180 | PRBool CERT_GovtApprovedBitSet(CERTCertificate *cert); |
1181 | |
1182 | SECStatus CERT_AddPermNickname(CERTCertificate *cert, char *nickname); |
1183 | |
1184 | CERTCertList *CERT_MatchUserCert(CERTCertDBHandle *handle, SECCertUsage usage, |
1185 | int nCANames, char **caNames, void *proto_win); |
1186 | |
1187 | CERTCertList *CERT_NewCertList(void); |
1188 | |
1189 | /* free the cert list and all the certs in the list */ |
1190 | void CERT_DestroyCertList(CERTCertList *certs); |
1191 | |
1192 | /* remove the node and free the cert */ |
1193 | void CERT_RemoveCertListNode(CERTCertListNode *node); |
1194 | |
1195 | /* equivalent to CERT_AddCertToListTailWithData(certs, cert, NULL) */ |
1196 | SECStatus CERT_AddCertToListTail(CERTCertList *certs, CERTCertificate *cert); |
1197 | |
1198 | /* equivalent to CERT_AddCertToListHeadWithData(certs, cert, NULL) */ |
1199 | SECStatus CERT_AddCertToListHead(CERTCertList *certs, CERTCertificate *cert); |
1200 | |
1201 | /* |
1202 | * The new cert list node takes ownership of "cert". "cert" is freed |
1203 | * when the list node is removed. |
1204 | */ |
1205 | SECStatus CERT_AddCertToListTailWithData(CERTCertList *certs, |
1206 | CERTCertificate *cert, void *appData); |
1207 | |
1208 | /* |
1209 | * The new cert list node takes ownership of "cert". "cert" is freed |
1210 | * when the list node is removed. |
1211 | */ |
1212 | SECStatus CERT_AddCertToListHeadWithData(CERTCertList *certs, |
1213 | CERTCertificate *cert, void *appData); |
1214 | |
1215 | typedef PRBool (*CERTSortCallback)(CERTCertificate *certa, |
1216 | CERTCertificate *certb, void *arg); |
1217 | SECStatus CERT_AddCertToListSorted(CERTCertList *certs, CERTCertificate *cert, |
1218 | CERTSortCallback f, void *arg); |
1219 | |
1220 | /* callback for CERT_AddCertToListSorted that sorts based on validity |
1221 | * period and a given time. |
1222 | */ |
1223 | PRBool CERT_SortCBValidity(CERTCertificate *certa, CERTCertificate *certb, |
1224 | void *arg); |
1225 | |
1226 | SECStatus CERT_CheckForEvilCert(CERTCertificate *cert); |
1227 | |
1228 | CERTGeneralName *CERT_GetCertificateNames(CERTCertificate *cert, |
1229 | PLArenaPool *arena); |
1230 | |
1231 | CERTGeneralName *CERT_GetConstrainedCertificateNames( |
1232 | const CERTCertificate *cert, PLArenaPool *arena, |
1233 | PRBool includeSubjectCommonName); |
1234 | |
1235 | /* |
1236 | * Creates or adds to a list of all certs with a give subject name, sorted by |
1237 | * validity time, newest first. Invalid certs are considered older than |
1238 | * valid certs. If validOnly is set, do not include invalid certs on list. |
1239 | */ |
1240 | CERTCertList *CERT_CreateSubjectCertList(CERTCertList *certList, |
1241 | CERTCertDBHandle *handle, |
1242 | const SECItem *name, PRTime sorttime, |
1243 | PRBool validOnly); |
1244 | |
1245 | /* |
1246 | * remove certs from a list that don't have keyUsage and certType |
1247 | * that match the given usage. |
1248 | */ |
1249 | SECStatus CERT_FilterCertListByUsage(CERTCertList *certList, SECCertUsage usage, |
1250 | PRBool ca); |
1251 | |
1252 | /* |
1253 | * check the key usage of a cert against a set of required values |
1254 | */ |
1255 | SECStatus CERT_CheckKeyUsage(CERTCertificate *cert, unsigned int requiredUsage); |
1256 | |
1257 | /* |
1258 | * return required key usage and cert type based on cert usage |
1259 | */ |
1260 | SECStatus CERT_KeyUsageAndTypeForCertUsage(SECCertUsage usage, PRBool ca, |
1261 | unsigned int *retKeyUsage, |
1262 | unsigned int *retCertType); |
1263 | /* |
1264 | * return required trust flags for various cert usages for CAs |
1265 | */ |
1266 | SECStatus CERT_TrustFlagsForCACertUsage(SECCertUsage usage, |
1267 | unsigned int *retFlags, |
1268 | SECTrustType *retTrustType); |
1269 | |
1270 | /* |
1271 | * Find all user certificates that match the given criteria. |
1272 | * |
1273 | * "handle" - database to search |
1274 | * "usage" - certificate usage to match |
1275 | * "oneCertPerName" - if set then only return the "best" cert per |
1276 | * name |
1277 | * "validOnly" - only return certs that are curently valid |
1278 | * "proto_win" - window handle passed to pkcs11 |
1279 | */ |
1280 | CERTCertList *CERT_FindUserCertsByUsage(CERTCertDBHandle *handle, |
1281 | SECCertUsage usage, |
1282 | PRBool oneCertPerName, PRBool validOnly, |
1283 | void *proto_win); |
1284 | |
1285 | /* |
1286 | * Find a user certificate that matchs the given criteria. |
1287 | * |
1288 | * "handle" - database to search |
1289 | * "nickname" - nickname to match |
1290 | * "usage" - certificate usage to match |
1291 | * "validOnly" - only return certs that are curently valid |
1292 | * "proto_win" - window handle passed to pkcs11 |
1293 | */ |
1294 | CERTCertificate *CERT_FindUserCertByUsage(CERTCertDBHandle *handle, |
1295 | const char *nickname, |
1296 | SECCertUsage usage, PRBool validOnly, |
1297 | void *proto_win); |
1298 | |
1299 | /* |
1300 | * Filter a list of certificates, removing those certs that do not have |
1301 | * one of the named CA certs somewhere in their cert chain. |
1302 | * |
1303 | * "certList" - the list of certificates to filter |
1304 | * "nCANames" - number of CA names |
1305 | * "caNames" - array of CA names in string(rfc 1485) form |
1306 | * "usage" - what use the certs are for, this is used when |
1307 | * selecting CA certs |
1308 | */ |
1309 | SECStatus CERT_FilterCertListByCANames(CERTCertList *certList, int nCANames, |
1310 | char **caNames, SECCertUsage usage); |
1311 | |
1312 | /* |
1313 | * Filter a list of certificates, removing those certs that aren't user certs |
1314 | */ |
1315 | SECStatus CERT_FilterCertListForUserCerts(CERTCertList *certList); |
1316 | |
1317 | /* |
1318 | * Filter a list of certificates, removing those certs that don't match the |
1319 | * nickname. |
1320 | */ |
1321 | SECStatus CERT_FilterCertListByNickname(CERTCertList *certList, char *nickname, |
1322 | void *pwarg); |
1323 | |
1324 | /* return true if cert is in cert list */ |
1325 | PRBool CERT_IsInList(const CERTCertificate *cert, const CERTCertList *certList); |
1326 | |
1327 | /* returned certList is the intersection of the certs on certList and the |
1328 | * certs on filterList */ |
1329 | SECStatus CERT_FilterCertListByCertList(CERTCertList *certList, |
1330 | const CERTCertList *filterList); |
1331 | |
1332 | /* |
1333 | * Collect the nicknames from all certs in a CertList. If the cert is not |
1334 | * valid, append a string to that nickname. |
1335 | * |
1336 | * "certList" - the list of certificates |
1337 | * "expiredString" - the string to append to the nickname of any expired cert |
1338 | * "notYetGoodString" - the string to append to the nickname of any cert |
1339 | * that is not yet valid |
1340 | */ |
1341 | CERTCertNicknames *CERT_NicknameStringsFromCertList(CERTCertList *certList, |
1342 | char *expiredString, |
1343 | char *notYetGoodString); |
1344 | |
1345 | /* |
1346 | * Extract the nickname from a nickmake string that may have either |
1347 | * expiredString or notYetGoodString appended. |
1348 | * |
1349 | * Args: |
1350 | * "namestring" - the string containing the nickname, and possibly |
1351 | * one of the validity label strings |
1352 | * "expiredString" - the expired validity label string |
1353 | * "notYetGoodString" - the not yet good validity label string |
1354 | * |
1355 | * Returns the raw nickname |
1356 | */ |
1357 | char *(char *namestring, char *expiredString, |
1358 | char *notYetGoodString); |
1359 | |
1360 | /* |
1361 | * Given a certificate, return a string containing the nickname, and possibly |
1362 | * one of the validity strings, based on the current validity state of the |
1363 | * certificate. |
1364 | * |
1365 | * "arena" - arena to allocate returned string from. If NULL, then heap |
1366 | * is used. |
1367 | * "cert" - the cert to get nickname from |
1368 | * "expiredString" - the string to append to the nickname if the cert is |
1369 | * expired. |
1370 | * "notYetGoodString" - the string to append to the nickname if the cert is |
1371 | * not yet good. |
1372 | */ |
1373 | char *CERT_GetCertNicknameWithValidity(PLArenaPool *arena, |
1374 | CERTCertificate *cert, |
1375 | char *expiredString, |
1376 | char *notYetGoodString); |
1377 | |
1378 | /* |
1379 | * Return the string representation of a DER encoded distinguished name |
1380 | * "dername" - The DER encoded name to convert |
1381 | */ |
1382 | char *CERT_DerNameToAscii(SECItem *dername); |
1383 | |
1384 | /* |
1385 | * Supported usage values and types: |
1386 | * certUsageSSLClient |
1387 | * certUsageSSLServer |
1388 | * certUsageSSLServerWithStepUp |
1389 | * certUsageEmailSigner |
1390 | * certUsageEmailRecipient |
1391 | * certUsageObjectSigner |
1392 | */ |
1393 | |
1394 | CERTCertificate *CERT_FindMatchingCert(CERTCertDBHandle *handle, |
1395 | SECItem *derName, CERTCertOwner owner, |
1396 | SECCertUsage usage, PRBool preferTrusted, |
1397 | PRTime validTime, PRBool validOnly); |
1398 | |
1399 | /* |
1400 | * Acquire the global lock on the cert database. |
1401 | * This lock is currently used for the following operations: |
1402 | * adding or deleting a cert to either the temp or perm databases |
1403 | * converting a temp to perm or perm to temp |
1404 | * changing(maybe just adding?) the trust of a cert |
1405 | * adjusting the reference count of a cert |
1406 | */ |
1407 | void CERT_LockDB(CERTCertDBHandle *handle); |
1408 | |
1409 | /* |
1410 | * Free the global cert database lock. |
1411 | */ |
1412 | void CERT_UnlockDB(CERTCertDBHandle *handle); |
1413 | |
1414 | /* |
1415 | * Get the certificate status checking configuratino data for |
1416 | * the certificate database |
1417 | */ |
1418 | CERTStatusConfig *CERT_GetStatusConfig(CERTCertDBHandle *handle); |
1419 | |
1420 | /* |
1421 | * Set the certificate status checking information for the |
1422 | * database. The input structure becomes part of the certificate |
1423 | * database and will be freed by calling the 'Destroy' function in |
1424 | * the configuration object. |
1425 | */ |
1426 | void CERT_SetStatusConfig(CERTCertDBHandle *handle, CERTStatusConfig *config); |
1427 | |
1428 | /* |
1429 | * Acquire the cert reference count lock |
1430 | * There is currently one global lock for all certs, but I'm putting a cert |
1431 | * arg here so that it will be easy to make it per-cert in the future if |
1432 | * that turns out to be necessary. |
1433 | */ |
1434 | void CERT_LockCertRefCount(CERTCertificate *cert); |
1435 | |
1436 | /* |
1437 | * Release the cert reference count lock |
1438 | */ |
1439 | void CERT_UnlockCertRefCount(CERTCertificate *cert); |
1440 | |
1441 | /* |
1442 | * Digest the cert's subject public key using the specified algorithm. |
1443 | * NOTE: this digests the value of the BIT STRING subjectPublicKey (excluding |
1444 | * the tag, length, and number of unused bits) rather than the whole |
1445 | * subjectPublicKeyInfo field. |
1446 | * |
1447 | * The necessary storage for the digest data is allocated. If "fill" is |
1448 | * non-null, the data is put there, otherwise a SECItem is allocated. |
1449 | * Allocation from "arena" if it is non-null, heap otherwise. Any problem |
1450 | * results in a NULL being returned (and an appropriate error set). |
1451 | */ |
1452 | extern SECItem *CERT_GetSubjectPublicKeyDigest(PLArenaPool *arena, |
1453 | const CERTCertificate *cert, |
1454 | SECOidTag digestAlg, |
1455 | SECItem *fill); |
1456 | |
1457 | /* |
1458 | * Digest the cert's subject name using the specified algorithm. |
1459 | */ |
1460 | extern SECItem *CERT_GetSubjectNameDigest(PLArenaPool *arena, |
1461 | const CERTCertificate *cert, |
1462 | SECOidTag digestAlg, SECItem *fill); |
1463 | |
1464 | SECStatus CERT_CheckCRL(CERTCertificate *cert, CERTCertificate *issuer, |
1465 | const SECItem *dp, PRTime t, void *wincx); |
1466 | |
1467 | /* |
1468 | * Add a CERTNameConstraint to the CERTNameConstraint list |
1469 | */ |
1470 | extern CERTNameConstraint *CERT_AddNameConstraint( |
1471 | CERTNameConstraint *list, CERTNameConstraint *constraint); |
1472 | |
1473 | /* |
1474 | * Allocate space and copy CERTNameConstraint from src to dest. |
1475 | * Arena is used to allocate result(if dest eq NULL) and its members |
1476 | * SECItem data. |
1477 | */ |
1478 | extern CERTNameConstraint *CERT_CopyNameConstraint(PLArenaPool *arena, |
1479 | CERTNameConstraint *dest, |
1480 | CERTNameConstraint *src); |
1481 | |
1482 | /* |
1483 | * Verify name against all the constraints relevant to that type of |
1484 | * the name. |
1485 | */ |
1486 | extern SECStatus CERT_CheckNameSpace(PLArenaPool *arena, |
1487 | const CERTNameConstraints *constraints, |
1488 | const CERTGeneralName *currentName); |
1489 | |
1490 | /* |
1491 | * Extract and allocate the name constraints extension from the CA cert. |
1492 | * If the certificate contains no name constraints extension, but |
1493 | * CERT_GetImposedNameConstraints returns a name constraints extension |
1494 | * for the subject of the certificate, then that extension will be returned. |
1495 | */ |
1496 | extern SECStatus CERT_FindNameConstraintsExten( |
1497 | PLArenaPool *arena, CERTCertificate *cert, |
1498 | CERTNameConstraints **constraints); |
1499 | |
1500 | /* |
1501 | * Initialize a new GERTGeneralName fields (link) |
1502 | */ |
1503 | extern CERTGeneralName *CERT_NewGeneralName(PLArenaPool *arena, |
1504 | CERTGeneralNameType type); |
1505 | |
1506 | /* |
1507 | * Lookup a CERTGeneralNameType constant by its human readable string. |
1508 | */ |
1509 | extern CERTGeneralNameType CERT_GetGeneralNameTypeFromString( |
1510 | const char *string); |
1511 | |
1512 | /* |
1513 | * PKIX extension encoding routines |
1514 | */ |
1515 | extern SECStatus CERT_EncodePolicyConstraintsExtension( |
1516 | PLArenaPool *arena, CERTCertificatePolicyConstraints *constr, |
1517 | SECItem *dest); |
1518 | extern SECStatus CERT_EncodeInhibitAnyExtension( |
1519 | PLArenaPool *arena, CERTCertificateInhibitAny *inhibitAny, SECItem *dest); |
1520 | extern SECStatus CERT_EncodePolicyMappingExtension( |
1521 | PLArenaPool *arena, CERTCertificatePolicyMappings *maps, SECItem *dest); |
1522 | |
1523 | extern SECStatus CERT_EncodeInfoAccessExtension(PLArenaPool *arena, |
1524 | CERTAuthInfoAccess **info, |
1525 | SECItem *dest); |
1526 | extern SECStatus CERT_EncodeUserNotice(PLArenaPool *arena, |
1527 | CERTUserNotice *notice, SECItem *dest); |
1528 | |
1529 | extern SECStatus CERT_EncodeDisplayText(PLArenaPool *arena, SECItem *text, |
1530 | SECItem *dest); |
1531 | |
1532 | extern SECStatus CERT_EncodeCertPoliciesExtension(PLArenaPool *arena, |
1533 | CERTPolicyInfo **info, |
1534 | SECItem *dest); |
1535 | extern SECStatus CERT_EncodeNoticeReference(PLArenaPool *arena, |
1536 | CERTNoticeReference *reference, |
1537 | SECItem *dest); |
1538 | |
1539 | /* |
1540 | * Returns a pointer to a static structure. |
1541 | */ |
1542 | extern const CERTRevocationFlags *CERT_GetPKIXVerifyNistRevocationPolicy(void); |
1543 | |
1544 | /* |
1545 | * Returns a pointer to a static structure. |
1546 | */ |
1547 | extern const CERTRevocationFlags *CERT_GetClassicOCSPEnabledSoftFailurePolicy( |
1548 | void); |
1549 | |
1550 | /* |
1551 | * Returns a pointer to a static structure. |
1552 | */ |
1553 | extern const CERTRevocationFlags *CERT_GetClassicOCSPEnabledHardFailurePolicy( |
1554 | void); |
1555 | |
1556 | /* |
1557 | * Returns a pointer to a static structure. |
1558 | */ |
1559 | extern const CERTRevocationFlags *CERT_GetClassicOCSPDisabledPolicy(void); |
1560 | |
1561 | /* |
1562 | * Verify a Cert with libpkix |
1563 | * paramsIn control the verification options. If a value isn't specified |
1564 | * in paramsIn, it reverts to the application default. |
1565 | * paramsOut specifies the parameters the caller would like to get back. |
1566 | * the caller may pass NULL, in which case no parameters are returned. |
1567 | */ |
1568 | extern SECStatus CERT_PKIXVerifyCert(CERTCertificate *cert, |
1569 | SECCertificateUsage usages, |
1570 | CERTValInParam *paramsIn, |
1571 | CERTValOutParam *paramsOut, void *wincx); |
1572 | |
1573 | /* Makes old cert validation APIs(CERT_VerifyCert, CERT_VerifyCertificate) |
1574 | * to use libpkix validation engine. The function should be called ones at |
1575 | * application initialization time. |
1576 | * Function is not thread safe.*/ |
1577 | extern SECStatus CERT_SetUsePKIXForValidation(PRBool enable); |
1578 | |
1579 | /* The function return PR_TRUE if cert validation should use |
1580 | * libpkix cert validation engine. */ |
1581 | extern PRBool CERT_GetUsePKIXForValidation(void); |
1582 | |
1583 | /* |
1584 | * Allocate a parameter container of type CERTRevocationFlags, |
1585 | * and allocate the inner arrays of the given sizes. |
1586 | * To cleanup call CERT_DestroyCERTRevocationFlags. |
1587 | */ |
1588 | extern CERTRevocationFlags *CERT_AllocCERTRevocationFlags( |
1589 | PRUint32 number_leaf_methods, PRUint32 number_leaf_pref_methods, |
1590 | PRUint32 number_chain_methods, PRUint32 number_chain_pref_methods); |
1591 | |
1592 | /* |
1593 | * Destroy the arrays inside flags, |
1594 | * and destroy the object pointed to by flags, too. |
1595 | */ |
1596 | extern void CERT_DestroyCERTRevocationFlags(CERTRevocationFlags *flags); |
1597 | |
1598 | /* |
1599 | * Get istemp and isperm fields from a cert in a thread safe way. |
1600 | */ |
1601 | extern SECStatus CERT_GetCertIsTemp(const CERTCertificate *cert, PRBool *istemp); |
1602 | extern SECStatus CERT_GetCertIsPerm(const CERTCertificate *cert, PRBool *isperm); |
1603 | |
1604 | SEC_END_PROTOS |
1605 | |
1606 | #endif /* _CERT_H_ */ |
1607 | |