📄 pgpx509keys.c
字号:
/*
* X509 Key importing
*
* Copyright (C) 1996,1997,1998 Network Associates Inc. and affiliated companies.
* All rights reserved
*
* $Id: pgpX509Keys.c,v 1.64 1999/05/19 22:34:03 hal Exp $
*/
#include "pgpConfig.h"
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <string.h>
#include <ctype.h>
#include "pgpKDBInt.h"
#include "pgpTypes.h"
#include "pgpDebug.h"
#include "pgpMem.h"
#include "pgpRngPub.h"
#include "pgpRngPriv.h"
#include "pgpRngPars.h"
#include "pgpRngRead.h"
#include "pgpTrust.h"
#include "pgpTrstPkt.h"
#include "pgpContext.h"
#include "pgpX509Priv.h"
#include "pgpHashPriv.h"
#include "pgpPubKey.h"
#include "pgpOptionListPriv.h"
#include "pgpPktByte.h"
#include "pgpPipeline.h"
#include "pgpFileMod.h"
#include "pgpEncodePriv.h"
#include "pgpVMemMod.h"
#include "pgpAnnotate.h"
#include "pgpSigSpec.h"
#include "pgpTimeDate.h"
/* Use TIS ASN.1 compiler */
#include "pgpX509Cert_asn.h"
/* Whether or not to use short forms for X509 name conversions */
#ifndef PGP_X509SHORTNAMES
#define PGP_X509SHORTNAMES 1
#endif
#define CHKNONNULL(p,e) if (IsNull(p)) { \
(e) = kPGPError_OutOfMemory; \
goto error; \
}
#define CHKASNERR(e) if ((e) != 0) { \
if ((e) == kPGPASNError_ErrOutOfMemory) { \
(e) = kPGPError_OutOfMemory; \
} else { \
(e) = k509Error_InvalidCertificateFormat; \
} \
goto error; \
}
/* Error returns */
#define k509Error_NeededCertNotAvailable -10
#define k509Error_SelfSignedCert -20
#define k509Error_InvalidCertificateSignature -30
#define k509Error_InvalidCertificateFormat -40
/* Size limit on cert */
#define MAX_509_CERT_SIZE 65536
/* Commonly used tag values */
#define TAG_ZERO 0
#define TAG_INTEGER 2
#define TAG_BITSTRING 3
#define TAG_OCTETSTRING 4
#define TAG_NULL 5
#define TAG_OBJECT 6
#define TAG_SEQUENCE 16
#define TAG_SET 17
#define TAG_PRINTABLE 19
#define TAG_T61STRING 20
#define TAG_IA5STRING 22
#define TAG_UTCTIME 23
#define TAG_GENERALIZEDTIME 24
#define TAG_CONSTRUCTED 32
/* Tagging values for CHOICE fields */
#define ASN_EXPLICIT 0x80|0x20
#define ASN_IMPLICIT 0x80
#define ASN_GENERALNAME_RFC822NAME (1|ASN_EXPLICIT)
#define ASN_GENERALNAME_DNSNAME (2|ASN_EXPLICIT)
#define ASN_GENERALNAME_DIRECTORYNAME (4|ASN_EXPLICIT)
#define ASN_GENERALNAME_URI (6|ASN_EXPLICIT)
#define ASN_GENERALNAME_IPADDRESS (7|ASN_EXPLICIT)
#define ASN_GENERALNAME_REGISTEREDID (8|ASN_EXPLICIT)
#define ASN_DPNAME_GENERALNAMES (0|ASN_EXPLICIT)
#define elemsof(arr) (sizeof(arr)/sizeof(arr[0]))
#define EXPECT(t, v) if (t != v) { \
err = kPGPError_X509InvalidCertificateFormat; \
goto error; \
}
/* Our inserted Description or OU value */
static char s_pgpdescr[] = "PGPKeyCreation=0x";
/* RSA OID is (1, 2, 840, 113549, 1, 1, 1) */
static PGPByte const rsaoid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x01};
/* RSA with MD5 OID is (1, 2, 840, 113549, 1, 1, 4) */
static PGPByte const rsamd5oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x04};
/* RSA with MD2 OID is (1, 2, 840, 113549, 1, 1, 2) */
static PGPByte const rsamd2oid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x02};
/* RSA with SHA OID is (1, 2, 840, 113549, 1, 1, 5) */
static PGPByte const rsashaoid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7,
0x0d, 0x01, 0x01, 0x05};
/* DSA OID is (1, 2, 840, 10040, 4, 1) */
static PGPByte const dsaoid[] = {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x01};
/* DSA with SHA-1 OID is (1, 2, 840, 10040, 4, 3) */
static PGPByte const dsashaoid1[] = {0x2a, 0x86, 0x48, 0xce, 0x38, 0x04, 0x03};
/* Another variant (1 3 14 3 2 27) */
static PGPByte const dsashaoid2[] = {0x2b, 0x0e, 0x03, 0x02, 0x1b};
/* ElG OID is (1, 2, 840, 10046, 2, 1) */
static PGPByte const elgoid[] = {0x2a, 0x86, 0x48, 0xce, 0x3e, 0x02, 0x01};
/* CN (common-name) OID is (2, 5, 4, 3) */
static PGPByte const cnoid[] = {0x55, 0x04, 0x03};
/* RSA's OID for email address in RDN's: (1, 2, 840, 113549, 1, 9, 1) */
static PGPByte const emailoid[] = {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
0x09, 0x01};
static const char emailname[] = "EMAIL";
/* Issuer, subject alternative names (2, 5, 29, 17) and (2, 5, 29, 18) */
static PGPByte const issaltnameoid[] = {0x55, 0x1d, 0x11};
static PGPByte const subaltnameoid[] = {0x55, 0x1d, 0x12};
/* Extensions */
/* Basic constraints (2, 5, 29, 19) */
static PGPByte const bconstraintsoid[] = {0x55, 0x1d, 0x13};
/* Key usage (2, 5, 29, 15) */
static PGPByte const keyusageoid[] = {0x55, 0x1d, 0x0f};
/* Issuer Distribution Point (2, 5, 29, 28) */
static PGPByte const issdistpoint[] = {0x55, 0x1d, 0x1c};
/* Certificate Distribution Point (2, 5, 29, 31) */
static PGPByte const certdistpoint[] = {0x55, 0x1d, 0x1f};
/* Need an OID for PGP extension */
/* PGP root is (1 3 6 1 4 1 3401 8), append (1 1) for us */
static PGPByte const pgpextensionoid[] = {0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
0x01, 0x9a, 0x49, 0x08, 0x01, 0x01};
/* Table to convert DN field OID's to letter codes per RFC2253 */
/* Indexed by the last value in a (2, 5, 4, X) OID */
static const char *dnnames[] = {
NULL, NULL, NULL,
"CN", /* 3 == commonName */
NULL, NULL,
"C", /* 6 == countryName */
"L", /* 7 == localityName */
"ST", /* 8 == stateOrProvinceName */
"STREET", /* 9 == streetAddress */
"O", /* 10 == organizationName */
"OU", /* 11 == organizationalUnitName */
};
#if PRINTDEBUG509
/* Used for debugging, to print out the tags as we see them */
static struct {
int tag;
char *name;
} const tagnames[] = {
{TAG_INTEGER, "Integer"},
{TAG_BITSTRING, "Bitstring"},
{TAG_OCTETSTRING, "Octetstring"},
{TAG_NULL, "Null"},
{TAG_OBJECT, "Object"},
{TAG_SEQUENCE, "Sequence"},
{TAG_SET, "Set"},
{TAG_PRINTABLE, "Printablestring"},
{TAG_T61STRING, "T61string"},
{TAG_IA5STRING, "IA5string"},
{TAG_UTCTIME, "UTCTime"}
{TAG_GENERALIZEDTIME, "GeneralizedTime"}
};
#endif
#if PRINTDEBUG509
static void
printtagname (int tag)
{
int i;
int printed = 0;
printf ("0x%02x", tag);
for (i=0; i<sizeof(tagnames)/sizeof(tagnames[0]); ++i) {
if (tagnames[i].tag == tag) {
printf (" (%s)", tagnames[i].name);
printed = 1;
break;
}
}
if (!printed)
printf ("(<Unknown>)");
}
#endif
/* ASN memory management */
static void *
sASNAlloc( PGPASN_MemoryMgr *asnmgr, size_t requestSize)
{
PGPMemoryMgrRef mgr = asnmgr->customValue;
return PGPNewData( mgr, (PGPSize)requestSize, 0);
}
static int
sASNReAlloc( PGPASN_MemoryMgr *asnmgr, void **allocation,
size_t newAllocationSize )
{
PGPMemoryMgrRef mgr = asnmgr->customValue;
return (int)PGPReallocData( mgr, allocation, newAllocationSize, 0);
}
static int
sASNDeAlloc( PGPASN_MemoryMgr *asnmgr, void *allocation )
{
(void) asnmgr;
return (int)PGPFreeData( allocation );
}
static void
sSetupASNCONTEXT (PGPMemoryMgrRef mgr, PGPASN_CONTEXT *asnctx,
PGPASN_MemoryMgr *asnmgr)
{
asnctx->customValue = NULL;
asnctx->memMgr = asnmgr;
asnmgr->customValue = (void *)mgr;
asnmgr->allocProc = sASNAlloc;
asnmgr->reallocProc = sASNReAlloc;
asnmgr->deallocProc = sASNDeAlloc;
}
/* Return bit number of highest bit in byte */
static int
hibit(int n)
{
int bit = 7;
int val = 0x80;
if (n == 0)
return -1;
while ((val & n) == 0) {
val >>= 1;
--bit;
}
return bit;
}
#if 0
/* Unused */
/* Return the length of the DER length field for the specified length */
static PGPUInt32
_lenlen (PGPUInt32 length)
{
if (length < 0x80)
return 1;
if (length < 0x100)
return 2;
if (length < 0x10000)
return 3;
if (length < 0x1000000)
return 4;
return 5;
}
#endif
/* Read start of an X.509 object */
static int
dotaglen(PGPByte **buf, PGPSize *length)
{
PGPByte tag = *(*buf)++ & 0x1f;
PGPSize len = *(*buf)++;
if (len & 0x80) {
PGPByte lenlen = len & 0x7f;
len = 0;
while (lenlen--) {
len <<= 8;
len |= *(*buf)++;
}
}
*length = len;
#if PRINTDEBUG509
printf ("tag ");
printtagname(tag);
printf (", length 0x%x\n", len);
#endif
return tag;
}
/* Read a three byte value and skip past it */
static int
dolen3(PGPByte **buf)
{
int len;
len = *(*buf)++;
len <<= 8;
len |= *(*buf)++;
len <<= 8;
len |= *(*buf)++;
return len;
}
#if 0
/*
* Convert an RFC2253 LDAP-format string to an X.509 PGPASN_Name
* structure in *dname.
* Any quoting used in input must be double quotes around
* the whole value, as in O="Network Associates, Inc.".
*/
static PGPError
sEncodeDN (PGPMemoryMgrRef mgr, PGPASN_CONTEXT *asnctx, char const *str,
PGPASN_Name **pname)
{
PGPASN_Name *name = NULL;
PGPASN_RDNSequence *rdns ;
PGPASN_RelativeDistinguishedName *rdn;
PGPASN_AttributeTypeAndValue *atv;
PGPASN_PrintableString *ps = NULL; /* May be IA5String */
PGPByte *psbuf = NULL;
PGPSize psbufsize;
char *s;
char *eq, *cq, *com = NULL;
PGPUInt32 i = 0;
PGPSize slen;
char *scopy;
PGPBoolean email;
PGPError err = kPGPError_NoErr;
PGPByte oid[sizeof(emailoid)];
PGPSize oidsize;
*pname = NULL;
slen = strlen(str);
scopy = PGPNewData( mgr, slen+1, 0 );
pgpCopyMemory( str, scopy, slen+1 );
s = scopy;
name = pgpasn_NewName (asnctx);
CHKNONNULL( name, err );
rdns = pgpasn_NewRDNSequence (asnctx);
CHKNONNULL( rdns, err );
name->CHOICE_field_type = PGPASN_ID_RDNSequence;
name->data = rdns;
while (*s) {
if ((eq = strchr(s, '=')) == NULL) {
err = kPGPError_BadParams;
goto error;
}
*eq = '\0';
if( strcmp(emailname, s) == 0 ) {
email = TRUE;
} else {
email = FALSE;
for (i=0; i<elemsof(dnnames); ++i) {
if (strcmp(dnnames[i], s) == 0)
break;
}
if (i >= elemsof(dnnames)) {
err = kPGPError_BadParams;
goto error;
}
}
s = eq + 1;
if (*s == '"') {
if ((cq = strchr(++s, '"')) == NULL) {
err = kPGPError_BadParams;
goto error;
}
*cq = '\0';
} else {
cq = NULL;
if ((com = strchr(s, ',')) == NULL)
com = s + strlen(s);
*com = '\0';
}
/* At this point, s points at the value, null terminated. */
/* i holds the index of the attribute, or email is true */
++rdns->n;
rdn = pgpasn_NewRelativeDistinguishedName (asnctx);
CHKNONNULL( rdn, err );
rdns->elt[rdns->n++] = rdn;
atv = pgpasn_NewAttributeTypeAndValue (asnctx);
CHKNONNULL( atv, err );
rdn->elt[0] = atv;
rdn->n = 1;
/* Insert attribute OID */
if( email ) {
oidsize = sizeof(emailoid);
pgpCopyMemory( emailoid, oid, oidsize );
} else {
oidsize = sizeof(cnoid);
pgpCopyMemory( cnoid, oid, oidsize );
oid[oidsize-1] = i;
}
pgpasn_PutOctVal (asnctx, &atv->type, oid, oidsize);
/* Insert attribute value */
ps = pgpasn_NewPrintableString (asnctx);
CHKNONNULL( ps, err );
pgpasn_PutOctVal (asnctx, ps, s, strlen(s));
psbufsize = pgpasn_SizeofPrintableString (asnctx, ps, TRUE);
psbuf = PGPNewData( mgr, psbufsize, 0 );
CHKNONNULL( psbuf, err );
if( email )
pgpasn_PackIA5String( asnctx, psbuf, psbufsize, ps, &err );
else
pgpasn_PackPrintableString( asnctx, psbuf, psbufsize, ps, &err );
CHKASNERR( err );
pgpasn_PutOctVal (asnctx, &atv->value, psbuf, psbufsize);
PGPFreeData( psbuf );
psbuf = NULL;
pgpasn_FreePrintableString( asnctx, ps );
ps = NULL;
if (cq) {
s = cq+2;
if (s[-1] != ',') {
err = kPGPError_BadParams;
goto error;
}
} else {
s = com+1;
}
}
PGPFreeData( scopy );
*pname = name;
return kPGPError_NoErr;
error:
if (scopy)
PGPFreeData( scopy );
if (ps)
pgpasn_FreePrintableString( asnctx, ps );
if (psbuf)
PGPFreeData( psbuf );
if (name)
pgpasn_FreeName( asnctx, name );
return err;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -