1
/**************************************************************************
2
*** COPYRIGHT (c) 2002 by TransNexus, Inc. ***
4
*** This software is property of TransNexus, Inc. ***
5
*** This software is freely available under license from TransNexus. ***
6
*** The license terms and conditions for free use of this software by ***
7
*** third parties are defined in the OSP Toolkit Software License ***
8
*** Agreement (LICENSE.txt). Any use of this software by third ***
9
*** parties, which does not comply with the terms and conditions of the ***
10
*** OSP Toolkit Software License Agreement is prohibited without ***
11
*** the prior, express, written consent of TransNexus, Inc. ***
13
*** Thank you for using the OSP ToolKit(TM). Please report any bugs, ***
14
*** suggestions or feedback to support@transnexus.com ***
16
**************************************************************************/
25
* ospx509.c - Member functions for X509 Certificate object.
29
#include "osp/ospasn1.h"
30
#include "osp/osppkcs1.h"
31
#include "osp/ospx509.h"
32
#include "osp/ospx500.h"
33
#include "osp/osptnlog.h"
34
#include "osp/ospostime.h"
35
#include "osp/ospcrypto.h"
39
/* ---------------------------------------------------------*/
40
/* Member functions */
41
/* ---------------------------------------------------------*/
43
#define PROVIDERDOMAIN "transnexus.com"
44
#define PROVIDERINFO "transnexus.com %ld %ld"
47
OSPPX509CertGetCustDeviceId(
48
OSPTASN1OBJECT *ospvCertificate,
49
unsigned long *ospvCustomerId,
50
unsigned long *ospvDeviceId)
52
int errorcode = OSPC_ERR_NO_ERROR;
53
OSPTASN1ELEMENTINFO *eInfo = OSPC_OSNULL;
54
char *domainName = PROVIDERDOMAIN;
55
unsigned domainNameLength = sizeof(PROVIDERDOMAIN)-1;
56
unsigned dataLength = 0;
57
char *data = OSPC_OSNULL;
58
char *cptr = OSPC_OSNULL;
59
char *lcptr = OSPC_OSNULL;
60
char *pname = OSPC_OSNULL;
61
char *value = OSPC_OSNULL;
66
/* Get the subject element */
67
errorcode = OSPPX509CertTestContext(ospvCertificate);
69
if (errorcode == OSPC_ERR_NO_ERROR)
71
/* Get pointer to parse result that is head of subject name */
72
errorcode = OSPPASN1ObjectGetElementByDataRef(ospvCertificate, &eInfo,
73
OSPEDRID_CERT_SUBJECT);
75
if (errorcode == OSPC_ERR_NO_ERROR)
77
errorcode = OSPPASN1ElementGetElementData(eInfo,
78
(unsigned char **)&value,&dataLength);
82
if (errorcode == OSPC_ERR_NO_ERROR)
84
OSPM_MALLOC(data, char, dataLength+1);
86
if (data == OSPC_OSNULL)
88
errorcode = OSPC_ERR_X509_UNABLE_TO_ALLOCATE_SPACE;
89
OSPM_DBGERRORLOG(errorcode, "Unable to allocate space");
92
if (errorcode == OSPC_ERR_NO_ERROR)
94
OSPM_MEMCPY(data, value, dataLength);
95
data[dataLength] = '\0';
101
if (errorcode == OSPC_ERR_NO_ERROR)
103
/* Search for the string in domainName */
104
for (cptr = data; *cptr; cptr++)
106
/* Looking for a [ */
113
/* Found a [, is it followed by the domain name? */
115
if (strncmp(cptr, domainName, domainNameLength))
121
/* Domain Name Found, we ARE in the parameter OU element */
122
pname = OSPM_STRTOK((char *)cptr, " ", &lcptr); /* Skip domainname */
125
/* Get the next parameter name */
126
pname = OSPM_STRTOK((char *)OSPC_OSNULL, " :]", &lcptr);
127
if (pname == OSPC_OSNULL)
129
/* Parameter was not found, done */
133
/* Have a parameter name, get the value */
134
value = OSPM_STRTOK((char *)OSPC_OSNULL, " :]", &lcptr);
135
if (value == OSPC_OSNULL)
137
/* Badly formed paramter value pair, done */
141
/* We have a parameter and a value - which one? */
142
if (!strncmp(pname, "GWID", 4))
144
/* Found a gateway id */
145
*ospvDeviceId = atol(value);
149
if (!strncmp(pname, "CSID", 4))
151
/* Found a customer id */
152
*ospvCustomerId = atol(value);
161
OSPPASN1ElementDelete(&eInfo, 0);
169
OSPPX509CertCheckCertificateData(
170
OSPTASN1OBJECT *ospvCertInfo,
171
OSPTASN1OBJECT *ospvSignerPublicKey)
173
int errorcode = OSPC_ERR_NO_ERROR;
175
unsigned char *tbsCertificate = OSPC_OSNULL;
176
unsigned int tbsCertificateLength = 0;
177
OSPTASN1OBJECT *signature = OSPC_OSNULL;
178
/* OSPTASN1OBJECT *publicKey = OSPC_OSNULL; */
179
OSPTASN1OBJECT *certInfo = OSPC_OSNULL;
180
OSPTASN1ELEMENTINFO *elementInfo = OSPC_OSNULL;
181
char currentDate[OSPC_TIMESTRINGSIZE] = "";
182
char notBeforeString[OSPC_TIMESTRINGSIZE] = "";
183
char notAfterString[OSPC_TIMESTRINGSIZE] = "";
184
OSPTTIME currentTime = 0;
185
char *century = OSPC_OSNULL;
186
unsigned char *date = OSPC_OSNULL;
187
unsigned int dateLength = 0;
188
unsigned char *certificate = OSPC_OSNULL;
189
unsigned int certificateLength = 0;
191
errorcode = OSPPASN1ObjectGetElementInfo(ospvCertInfo, &elementInfo);
193
memset(¬BeforeString,0,sizeof(notBeforeString));
194
memset(¬AfterString,0,sizeof(notAfterString));
196
if (errorcode == OSPC_ERR_NO_ERROR)
198
/* Reparse the certificate */
199
errorcode = OSPPASN1ElementGetElementData(elementInfo,
200
&certificate, &certificateLength);
202
if (errorcode == OSPC_ERR_NO_ERROR)
204
errorcode = OSPPX509CertCreate(certificate, &certInfo);
209
/* To validate the certificate you need to verify the certificate
210
signature using teh TBSCertificate portion of the certificate being
211
validated. You also need to compre the not-before and not-after dates
212
against the current date.
214
if (errorcode == OSPC_ERR_NO_ERROR)
216
/* Check the certificate's signature */
217
if (errorcode == OSPC_ERR_NO_ERROR)
219
/* Get the "to be signed" part of the certificate */
220
errorcode = OSPPASN1ObjectGetElementByDataRef(certInfo,
221
&elementInfo, OSPEDRID_CERT_TBSCERTIFICATE);
223
if (errorcode == OSPC_ERR_NO_ERROR)
225
errorcode = OSPPASN1ElementGetElementData(elementInfo,
227
&tbsCertificateLength);
231
if (errorcode == OSPC_ERR_NO_ERROR)
233
/* Get the signature from certificate */
234
errorcode = OSPPASN1ObjectCopyElementObject(&signature,
235
certInfo, OSPEDRID_CERT_SIGNATURE);
238
if (errorcode == OSPC_ERR_NO_ERROR)
240
errorcode = OSPPCryptoVerify( signature, ospvSignerPublicKey,
241
tbsCertificate, tbsCertificateLength);
244
OSPM_FREE(tbsCertificate);
245
OSPPASN1ElementDelete(&(signature->ParseResults->ElementInfo),0);
246
OSPPASN1ObjectDelete(&signature);
248
/* OSPPASN1ElementDelete(&(publicKey->ParseResults->ElementInfo),0); */
249
/* OSPPASN1ObjectDelete(&publicKey); */
252
if (errorcode == OSPC_ERR_NO_ERROR)
254
/* Signature must be good. Check validity dates */
256
/* Get the current time - don't need milliseconds */
257
errorcode = OSPPOSTimeGetTime(¤tTime,
258
(unsigned int *)OSPC_OSNULL);
260
if (errorcode == OSPC_ERR_NO_ERROR)
262
/* Format the current time in YYYYMMDDhhmmssZ format */
263
errorcode = OSPPOSTimeFormatGMTTime(currentTime, "%Y%m%d%H%M%SZ",
267
if (errorcode == OSPC_ERR_NO_ERROR)
271
OSPM_FREE(elementInfo);
273
/* Get the Not before time from the certificate */
274
errorcode = OSPPASN1ObjectGetElementByDataRef(certInfo,
275
&elementInfo, OSPEDRID_CERT_NOTBEFORE);
277
if (errorcode == OSPC_ERR_NO_ERROR)
279
errorcode = OSPPASN1ElementGetContentData(elementInfo,
281
if (errorcode == OSPC_ERR_NO_ERROR)
283
if (dateLength != 13)
285
errorcode = OSPC_ERR_X509_INVALID_DATE;
286
OSPM_DBGERRORLOG(errorcode,
287
"Date is not 13 characters long");
291
/* Format the not before date */
292
century = (OSPM_MEMCMP(date, "49", 2) > 0)? "19" : "20";
293
OSPM_STRCPY(notBeforeString,century);
294
OSPM_STRNCAT(notBeforeString,(char *)date,13);
295
/*OSPM_SPRINTF(notBeforeString,"%s%13s.13s", century, date);*/
301
if (errorcode == OSPC_ERR_NO_ERROR)
303
if(elementInfo) /* !!! PS */
305
OSPM_FREE(elementInfo->Element);
306
elementInfo->ElementLength = 0;
307
OSPM_FREE(elementInfo);
309
/* Get the Not after time from the certificate */
310
errorcode = OSPPASN1ObjectGetElementByDataRef( certInfo,
311
&elementInfo, OSPEDRID_CERT_NOTAFTER);
313
if (errorcode == OSPC_ERR_NO_ERROR)
315
errorcode = OSPPASN1ElementGetContentData(elementInfo,
317
if (errorcode == OSPC_ERR_NO_ERROR)
319
if (dateLength != 13)
321
errorcode = OSPC_ERR_X509_INVALID_DATE;
322
OSPM_DBGERRORLOG(errorcode,
323
"Date is not 13 characters long");
327
/* Format the not after date */
328
century = (OSPM_MEMCMP(date, "49", 2) > 0)? "19" : "20";
329
OSPM_STRCPY(notAfterString,century);
330
OSPM_STRNCAT(notAfterString,(char *)date,13);
331
/*OSPM_SPRINTF(notAfterString,"%s%13s.13s", century, date);*/
335
if(elementInfo) /* !!! PS */
337
OSPM_FREE(elementInfo->Element);
338
elementInfo->ElementLength = 0;
339
OSPM_FREE(elementInfo);
343
if (errorcode == OSPC_ERR_NO_ERROR)
345
/* At this time, Only UTC times are supported. Format is
346
YYMMDDHHMMSSZ. Accorting to X509, if YY is less than 50, then the
347
century is 2000. If date is greater than 50, century is 1900.
348
After 2050, generalized time will be used (not supported), and that
349
will eliminate the problem since centurey is explicit in date. */
351
if ((OSPM_MEMCMP(currentDate,notBeforeString,
352
strlen(currentDate))<0) ||
353
(OSPM_MEMCMP(currentDate,notAfterString,
354
strlen(currentDate))>0))
356
errorcode = OSPC_ERR_X509_CERTIFICATE_EXPIRED;
357
#ifdef IGNOREOUTOFDATEERR
358
errorcode = OSPC_ERR_NOERROR;
360
OSPM_DBGERRORLOG(errorcode,
361
"Current date is outside certificate validity dates");
366
OSPPASN1ObjectDelete(&certInfo);
368
} /* OSPPX509CertCheckCertificateData */
373
OSPPX509CertValidateCertificate(
374
OSPTASN1OBJECT *ospvTestCertificate,
375
OSPTASN1OBJECT *ospvAuthorityCertificates[],
376
unsigned int ospvNumberOfAuthorityCertificates,
377
int *ospvParentCertificateIndex)
379
int errorcode = OSPC_ERR_NO_ERROR;
380
OSPTASN1OBJECT *publicKey = OSPC_OSNULL;
384
/* Loop through Authority Certificates to find issuer for testCert */
386
(errorcode == OSPC_ERR_NO_ERROR || errorcode == OSPC_ERR_X509_CA_NOT_FOUND) &&
387
(i < ospvNumberOfAuthorityCertificates); i ++)
389
/* Test ca certificate against test certificate */
390
errorcode = OSPPX509CertIsParentCertificate(
391
ospvAuthorityCertificates[i],
392
ospvTestCertificate);
394
if (errorcode != OSPC_ERR_X509_CA_NOT_FOUND)
396
/* Found the ca for the test certificate or a serious error */
402
if (errorcode == OSPC_ERR_NO_ERROR)
404
/* Get the public key from certificate */
405
errorcode = OSPPASN1ObjectCopyElementObject(&publicKey,
406
ospvAuthorityCertificates[i],
407
OSPEDRID_CERT_SUBJPUBKEYINFO);
410
if (errorcode == OSPC_ERR_NO_ERROR)
412
/* Check the test certificate to see if it is signed/not expired */
413
errorcode = OSPPX509CertCheckCertificateData(ospvTestCertificate,
417
if (errorcode == OSPC_ERR_NO_ERROR)
419
/* Is authority certificate self signed? */
420
if (OSPPX509CertIsParentCertificate(ospvAuthorityCertificates[i],
421
ospvAuthorityCertificates[i]))
423
/* Yes - is is a Self Signed Certificate */
424
/* Check ca certificate (self signed) to make sure it is valid */
425
errorcode = OSPPX509CertCheckCertificateData(
426
ospvAuthorityCertificates[i],
432
/* Nope, not self signed - continue down chain or return index
434
if (ospvParentCertificateIndex == OSPC_OSNULL)
436
/* Validate Certificate Chain */
437
errorcode = OSPPX509CertValidateCertificate(
438
ospvAuthorityCertificates[i],
439
ospvAuthorityCertificates,
440
ospvNumberOfAuthorityCertificates,
445
if(OSPC_OSNULL!=publicKey) /* !!! PS */
447
OSPPASN1ElementDelete(&(publicKey->ParseResults->ElementInfo),0);
448
OSPPASN1ObjectDelete(&publicKey);
452
if (errorcode == OSPC_ERR_NO_ERROR)
454
/* If supposed to return index, then set it here */
455
if (ospvParentCertificateIndex != OSPC_OSNULL)
457
*ospvParentCertificateIndex = i;
465
OSPPX509CertIsParentCertificate(
466
OSPTASN1OBJECT *ospvParentCertificate,
467
OSPTASN1OBJECT *ospvTestCertificate)
469
int errorcode = OSPC_ERR_NO_ERROR;
470
OSPTASN1OBJECT *parentCertInfo = OSPC_OSNULL;
471
OSPTASN1OBJECT *testCertInfo = OSPC_OSNULL;
472
OSPTASN1ELEMENTINFO *elementInfo1 = OSPC_OSNULL; /* !!! PS */
473
OSPTASN1ELEMENTINFO *elementInfo2 = OSPC_OSNULL; /* !!! PS */
474
unsigned char *certificate = OSPC_OSNULL;
475
unsigned int certificateLength = 0;
476
unsigned char *subjectName = OSPC_OSNULL;
477
unsigned int subjectNameLength = 0;
478
unsigned char *issuerName = OSPC_OSNULL;
479
unsigned int issuerNameLength = 0;
481
/* Reparse the superior certificate */
482
errorcode = OSPPASN1ObjectGetElementInfo(ospvParentCertificate,
485
if (errorcode == OSPC_ERR_NO_ERROR)
487
/* Reparse the certificate */
488
errorcode = OSPPASN1ElementGetElementData(elementInfo1,
489
&certificate, &certificateLength);
491
if (errorcode == OSPC_ERR_NO_ERROR)
493
errorcode = OSPPX509CertCreate(certificate, &parentCertInfo);
496
/* Reparse the test certificate */
497
if (errorcode == OSPC_ERR_NO_ERROR)
499
errorcode = OSPPASN1ObjectGetElementInfo(ospvTestCertificate,
503
if (errorcode == OSPC_ERR_NO_ERROR)
505
/* Reparse the certificate */
506
errorcode = OSPPASN1ElementGetElementData(elementInfo1,
507
&certificate, &certificateLength);
509
if (errorcode == OSPC_ERR_NO_ERROR)
511
errorcode = OSPPX509CertCreate(certificate, &testCertInfo);
516
if (errorcode == OSPC_ERR_NO_ERROR)
518
/* Get the parent certificate subject name */
519
errorcode = OSPPASN1ObjectGetElementByDataRef(parentCertInfo,
521
OSPEDRID_CERT_SUBJECT);
522
if (errorcode == OSPC_ERR_NO_ERROR)
524
errorcode = OSPPASN1ElementGetElementData(elementInfo1,
525
&subjectName, &subjectNameLength);
530
if (errorcode == OSPC_ERR_NO_ERROR)
532
/* Get the test certificate issuer name */
533
errorcode = OSPPASN1ObjectGetElementByDataRef(testCertInfo,
535
OSPEDRID_CERT_ISSUER);
536
if (errorcode == OSPC_ERR_NO_ERROR)
538
errorcode = OSPPASN1ElementGetElementData(elementInfo2,
539
&issuerName, &issuerNameLength);
544
if (errorcode == OSPC_ERR_NO_ERROR)
546
/* Now we have both Names. For now, assume they are formatted
547
exactly the same on both certificates. Should be able to do a
548
memcmp to make sure they are the same. If there is a possibility of
549
encoding differences (possible?) then it might be necessary to
550
add code to take each name apart and search and compare elements. */
552
errorcode = OSPC_ERR_X509_CA_NOT_FOUND;
553
if (issuerNameLength == subjectNameLength)
555
if (OSPM_MEMCMP(issuerName, subjectName, issuerNameLength) == 0)
557
errorcode = OSPC_ERR_NO_ERROR;
562
if(OSPC_OSNULL!=elementInfo1) /* !!! PS */
564
OSPPASN1ElementDelete(&elementInfo1,0);
566
if(OSPC_OSNULL!=elementInfo2) /* !!! PS */
568
OSPPASN1ElementDelete(&elementInfo2,0);
570
OSPPASN1ObjectDelete(&parentCertInfo);
571
OSPPASN1ObjectDelete(&testCertInfo);
573
} /* OSPPX509CertIsParentCertificate */
577
OSPPX509CertGetCertificate(
578
OSPTASN1OBJECT *ospvCertInfo,
579
unsigned char **ospvCertificate,
580
unsigned int *ospvCertificateLength)
582
int errorcode = OSPC_ERR_NO_ERROR;
583
OSPTASN1ELEMENTINFO *eInfo = OSPC_OSNULL;
585
*ospvCertificate = OSPC_OSNULL;
586
*ospvCertificateLength = 0;
588
errorcode = OSPPX509CertGetElement( ospvCertInfo,
589
OSPEDRID_CERTIFICATE,
591
if (eInfo != OSPC_OSNULL)
593
*ospvCertificate = eInfo->Element;
594
*ospvCertificateLength = eInfo->ElementLength;
603
OSPPX509CertGetElement(
604
OSPTASN1OBJECT *ospvCertInfo, /* In - X509 Cert Context */
605
OSPEASN1DATAREFID ospvDataRefId,
606
OSPTASN1ELEMENTINFO **ospvElementInfo)
608
int errorcode = OSPC_ERR_NO_ERROR;
609
OSPTASN1ELEMENTINFO *foundElement = OSPC_OSNULL;
611
errorcode = OSPPX509CertTestContext(ospvCertInfo);
612
if ( errorcode == OSPC_ERR_NO_ERROR)
614
errorcode = OSPPASN1ElementGet(ospvDataRefId,
615
ospvCertInfo->ParseResults, &foundElement);
618
*ospvElementInfo = foundElement;
625
OSPPX509CertTestContext(
626
OSPTASN1OBJECT *ospvCertInfo)
628
int errorcode = OSPC_ERR_NO_ERROR;
630
if (ospvCertInfo == OSPC_OSNULL)
632
errorcode = OSPC_ERR_X509_INVALID_CONTEXT;
633
OSPM_PRINTTOERR((stderr,"X509 CertInfo context is null pointer\n"));
643
unsigned char *ospvEncodedCertificate,
644
OSPTASN1OBJECT **ospvCert)
646
int errorcode = OSPC_ERR_NO_ERROR;
648
OSPM_MALLOC(*ospvCert, OSPTASN1OBJECT, sizeof(OSPTASN1OBJECT));
649
if (*ospvCert == OSPC_OSNULL)
651
errorcode = OSPC_ERR_CERT_MALLOC_FAILED;
652
OSPM_DBGERRORLOG(errorcode,
653
"malloc of new X509 Certificate failed");
657
OSPM_MEMSET(*ospvCert, 0, sizeof(OSPTASN1OBJECT));
660
if (errorcode == OSPC_ERR_NO_ERROR)
662
errorcode = OSPPX509CertSetCertificate(*ospvCert,
663
ospvEncodedCertificate);
671
OSPPX509CertSetCertificate(
672
OSPTASN1OBJECT *ospvCert,
673
unsigned char *ospvEncodedCertificate)
675
int errorcode = OSPC_ERR_NO_ERROR;
676
OSPTASN1ELEMENTINFO *eInfo = OSPC_OSNULL;
677
OSPTASN1PARSERESULT *parseResults = OSPC_OSNULL;
679
errorcode = OSPPX509CertTestContext(ospvCert);
681
if (errorcode == OSPC_ERR_NO_ERROR)
683
/* Get rid of the old certificate data */
684
OSPPASN1ElementDelete(&(ospvCert->ElementInfo),0);
685
OSPPASN1ElementParseDelete(&(ospvCert->ParseResults));
688
if (errorcode == OSPC_ERR_NO_ERROR)
690
errorcode = OSPPASN1ElementDecode(ospvEncodedCertificate, &eInfo, 0);
693
if (errorcode == OSPC_ERR_NO_ERROR)
695
errorcode = OSPPASN1ElementParse( eInfo, OSPEPTID_CERTIFICATE,
698
OSPC_ASN1_DATAREFID_CERTIFICATE);
701
if (errorcode == OSPC_ERR_NO_ERROR)
703
ospvCert->ElementInfo = eInfo;
704
ospvCert->ParseResults = parseResults;
710
OSPPASN1ElementDelete(&eInfo,0);
715
PTPResultsDelete(&parseResults);
725
OSPTASN1OBJECT **ospvCert)
727
int errorcode = OSPC_ERR_NO_ERROR;
729
errorcode = OSPPX509CertTestContext(*ospvCert);
730
if (errorcode == OSPC_ERR_NO_ERROR)
732
/* Get rid of the old certificate data */
733
OSPPASN1ObjectDelete(ospvCert);