📄 pgpx509keys.c
字号:
vbuf[o++] = 5; /* length */
vbuf[o++] = SIGSUB_CREATION;
vbuf[o++] = (PGPByte)(creationtime >> 24);
vbuf[o++] = (PGPByte)(creationtime >> 16);
vbuf[o++] = (PGPByte)(creationtime >> 8);
vbuf[o++] = (PGPByte)(creationtime >> 0);
vbuf[o++] = 5; /* length */
vbuf[o++] = SIGSUB_EXPIRATION;
vbuf[o++] = (PGPByte)(expirationtime >> 24);
vbuf[o++] = (PGPByte)(expirationtime >> 16);
vbuf[o++] = (PGPByte)(expirationtime >> 8);
vbuf[o++] = (PGPByte)(expirationtime >> 0);
pgpAssert (o == *vlength);
error:
return err;
}
/*
* Extract cert NotBefore time as a four byte time value, in bigendian form.
*/
static PGPError
sDecodeNotBefore4(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
PGPByte *cbuf)
{
PGPASN_Validity *val = &cert->tbsCertificate.validity;
PGPASN_CertificateValidityDate *cvd;
PGPASN_UTCTime *utc;
PGPUInt32 creationtime;
PGPError err = kPGPError_NoErr;
(void)asnctx;
cvd = &val->notBefore;
utc = (PGPASN_UTCTime *)cvd->data;
err = sDecodeUTCTime (utc->val, utc->len,
(PGPBoolean)(cvd->CHOICE_field_type!=PGPASN_ID_UTCTime),
&creationtime);
if( IsPGPError( err ) )
goto error;
*cbuf++ = (creationtime >> 24) & 0xff;
*cbuf++ = (creationtime >> 16) & 0xff;
*cbuf++ = (creationtime >> 8) & 0xff;
*cbuf++ = (creationtime >> 0) & 0xff;
error:
return err;
}
/*
* Convert from X.509 cert to PGP signature level subpacket, if any.
* If slbuf is NULL, set *sllength to the necessary length. Else
* store the data into slbuf, and treat *sllength as an input parameter
* telling what the length needs to be.
* We optionally create a PGP sig-level subpacket if it is a CA certificate.
*/
static PGPError
sDecodeSigLevel(PGPContextRef context, PGPASN_CONTEXT *asnctx,
PGPASN_Certificate *cert, PGPByte *slbuf, PGPSize *sllength)
{
PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
PGPASN_Extension *ext;
PGPASN_BasicConstraints *bc;
PGPUInt32 o;
PGPInt32 i;
PGPInt32 level = 0;
PGPBoolean gotCA = FALSE;
RingPool *pool = pgpContextGetRingPool( context );
PGPError err = kPGPError_NoErr;
pgpAssert( IsntNull( sllength ) );
/* Nothing to do if no extensions */
if (!exts) {
if( IsNull( slbuf ) ) {
*sllength = 0;
}
return kPGPError_NoErr;
}
for (i=0; (i<exts->n) && !gotCA; ++i) {
ext = exts->elt[i];
if (ext->extnID.len == sizeof(bconstraintsoid)
&& memcmp(ext->extnID.val, bconstraintsoid, ext->extnID.len)==0 ) {
/* Have a BasicConstraints extension */
pgpasn_UnpackBasicConstraints( asnctx, &bc, ext->extnValue.val,
ext->extnValue.len, &err );
if (err != 0) {
/* Skip if no good */
err = 0;
continue;
}
if ( IsntNull (bc->cA) && pgpasn_GetBoolVal( asnctx, bc->cA ) ) {
/* Here we have it as a CA. Assume maximum level */
if (IsNull( bc->pathLenConstraint) ) {
/* Max level if unconstrained */
level = 255;
} else {
level = pgpasn_GetIntVal( asnctx, bc->pathLenConstraint,
&err );
if( err ) {
/* Skip the whole thing if malformed */
err = 0;
pgpasn_FreeBasicConstraints( asnctx, bc );
continue;
}
/* In our units we use one level larger */
level += 1;
}
gotCA = TRUE;
}
pgpasn_FreeBasicConstraints( asnctx, bc );
}
}
if (!gotCA) {
if( IsNull( slbuf ) ) {
*sllength = 0;
}
return kPGPError_NoErr;
}
/* Here we need to create a sig level packet */
if( IsNull( slbuf ) ) {
/* One byte of len, one of type, one of level, one of trust */
*sllength = 4;
return kPGPError_NoErr;
}
pgpAssert (*sllength == 4);
o = 0;
slbuf[o++] = 3; /* length */
slbuf[o++] = SIGSUB_TRUST;
slbuf[o++] = level;
slbuf[o++] = ringTrustOldToExtern( pool, kPGPKeyTrust_Complete );
pgpAssert (o == *sllength);
return err;
}
/*
* Convert from X.509 cert to PGP key usage subpacket, if any.
* If kubuf is NULL, set *kulength to the necessary length. Else
* store the data into kubuf, and treat *kulength as an input parameter
* telling what the length needs to be.
* We optionally create a PGP sig-level subpacket if it is a CA certificate.
*/
static PGPError
sDecodeKeyUsage(PGPASN_CONTEXT *asnctx,
PGPASN_Certificate *cert, PGPByte *kubuf, PGPSize *kulength)
{
PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
PGPASN_Extension *ext;
PGPASN_KeyUsage *ku;
PGPUInt32 o;
PGPInt32 i;
PGPUInt32 kbits, kusage = 0;
PGPBoolean gotKU = FALSE;
PGPError err = kPGPError_NoErr;
pgpAssert( IsntNull( kulength ) );
/* Nothing to do if no extensions */
if (!exts) {
if( IsNull( kubuf ) ) {
*kulength = 0;
}
return kPGPError_NoErr;
}
for (i=0; (i<exts->n) && !gotKU; ++i) {
ext = exts->elt[i];
if (ext->extnID.len == sizeof(keyusageoid)
&& memcmp(ext->extnID.val, keyusageoid, ext->extnID.len)==0 ) {
/* Have a KeyUsage extension */
pgpasn_UnpackKeyUsage( asnctx, &ku, ext->extnValue.val,
ext->extnValue.len, &err );
if (err != 0) {
/* Skip if no good */
err = 0;
continue;
}
/* Coerce as an int value to get the bits */
kbits = pgpasn_GetIntVal( asnctx,
(PGPASN_VariableBlock *)ku, &err );
if (err != 0) {
/* Skip if no good */
err = 0;
pgpasn_FreeKeyUsage( asnctx, ku );
continue;
}
kusage = 0;
if (kbits & (PGPASN_KeyUsage_digitalSignature |
PGPASN_KeyUsage_nonRepudiation))
kusage |= SIGSUBF_KEYFLAG0_USAGE_SIGN;
if (kbits & (PGPASN_KeyUsage_keyEncipherment |
PGPASN_KeyUsage_dataEncipherment |
PGPASN_KeyUsage_keyAgreement))
kusage |= SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_COMM |
SIGSUBF_KEYFLAG0_USAGE_ENCRYPT_STORAGE;
if (kbits & (PGPASN_KeyUsage_keyCertSign |
PGPASN_KeyUsage_cRLSign))
kusage |= SIGSUBF_KEYFLAG0_USAGE_CERTIFY;
gotKU = TRUE;
pgpasn_FreeKeyUsage( asnctx, ku );
}
}
if (!gotKU) {
if( IsNull( kubuf ) ) {
*kulength = 0;
}
return kPGPError_NoErr;
}
/* Here we need to create a key usage packet */
if( IsNull( kubuf ) ) {
/* One byte of len, one of type, one of usage */
*kulength = 3;
return kPGPError_NoErr;
}
pgpAssert (*kulength == 3);
o = 0;
kubuf[o++] = 2; /* length */
kubuf[o++] = SIGSUB_KEYFLAGS;
kubuf[o++] = kusage;
pgpAssert (o == *kulength);
return err;
}
/*
* Extract PGP Key Creation field from cert, if available.
* Return zero if not.
* We try to encode it in the Description or, failing that, OrgUnit
* fields of the subject DN.
* If not there, we look for our custom extension.
*/
static PGPUInt32
sDecodeKeyCreation(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert)
{
PGPASN_RDNSequence *name;
PGPASN_RelativeDistinguishedName *rdn;
PGPASN_AttributeTypeAndValue *atv;
PGPASN_DirectoryString *dstr;
PGPASN_VariableBlock *vb;
PGPASN_Extensions *exts;
PGPASN_Extension *ext;
PGPASN_PGPExtension *pe;
PGPASN_UTCTime *utc;
PGPUInt32 dateval = 0;
PGPBoolean found;
PGPInt32 i, j, k;
char *bf;
PGPError err = kPGPError_NoErr;
found = FALSE;
name = (PGPASN_RDNSequence *)cert->tbsCertificate.subject.data;
/* Loop over elements of RDN sequence */
for (i=0; i<name->n && !found; ++i) {
rdn = name->elt[i];
for (j=0; j<rdn->n && !found; ++j) {
atv = rdn->elt[j];
/* Look for OU or Description */
if (atv->type.len == 3 &&
atv->type.val[0] == cnoid[0] && atv->type.val[1] == cnoid[1] &&
(atv->type.val[2] == 11 || atv->type.val[2] == 13)) {
pgpasn_UnpackDirectoryString( asnctx, &dstr,
atv->value.val, atv->value.len, &err );
if (err != 0) {
/* Skip if unprintable string */
err = 0;
continue;
}
vb = dstr->data;
if (vb->len == sizeof(s_pgpdescr)-1 + 8 &&
pgpMemoryEqual (vb->val, s_pgpdescr,
sizeof(s_pgpdescr)-1) ) {
/* Have a match, parse date value */
found = TRUE;
bf = (char *)vb->val + sizeof(s_pgpdescr)-1;
for (k=0; k<8; ++k) {
dateval = (dateval << 4) |
((bf[k] <= '9') ? (bf[k] - '0')
: (bf[k] <= 'F') ? (bf[k] - 'A' + 10)
: (bf[k] - 'a' + 10));
}
pgpasn_FreeDirectoryString( asnctx, dstr );
break;
}
pgpasn_FreeDirectoryString( asnctx, dstr );
}
}
}
if (found)
return dateval;
/* Now check extensions */
exts = cert->tbsCertificate.extensions;
if (IsNull(exts))
return dateval;
/* Check extensions for PGP special */
for (i=0; i<exts->n && !found; ++i) {
ext = exts->elt[i];
if (ext->extnID.len == sizeof(pgpextensionoid)
&& memcmp(ext->extnID.val, pgpextensionoid, ext->extnID.len)==0 ) {
/* Have a match */
pgpasn_UnpackPGPExtension( asnctx, &pe,
ext->extnValue.val, ext->extnValue.len, &err );
if (err != 0) {
/* Skip if can't handle */
err = 0;
continue;
}
utc = (PGPASN_UTCTime *)pe->keyCreation.data;
err = sDecodeUTCTime (utc->val, utc->len,
(PGPBoolean)
(pe->keyCreation.CHOICE_field_type!=PGPASN_ID_UTCTime),
&dateval);
if (err == kPGPError_NoErr)
found = TRUE;
pgpasn_FreePGPExtension( asnctx, pe );
}
}
return dateval;
}
/*
* Convert from X.509 cert to PGP style sig packet.
* If sigbuf is NULL, set *siglength to the necessary length. Else
* store the data into sigbuf, and treat *siglength as an input parameter
* telling what the length needs to be.
*/
static PGPError
sDecodeSig(PGPContextRef context, PGPASN_CONTEXT *asnctx,
PGPASN_Certificate *cert, PGPByte loversion,
PGPByte *sigBuf, PGPSize *sigLength)
{
PGPSize certlen;
PGPSize siglen;
PGPSize extralen;
PGPSize certlenlen;
PGPSize validitylen;
PGPSize siglevellen;
PGPSize keyusagelen;
PGPUInt32 o;
PGPPublicKeyAlgorithm sigalg;
PGPHashAlgorithm hashalg;
PGPError err = kPGPError_NoErr;
pgpAssert( IsntNull( sigLength ) );
if( IsNull( sigBuf ) )
*sigLength = 0;
/* Get length of validity info */
err = sDecodeValidity (asnctx, cert, NULL, &validitylen);
if (IsPGPError(err))
goto error;
/* Get length of signing-level info */
err = sDecodeSigLevel (context, asnctx, cert, NULL, &siglevellen);
if (IsPGPError(err))
goto error;
/* Get length of key-usage info */
err = sDecodeKeyUsage (asnctx, cert, NULL, &keyusagelen);
if (IsPGPError(err))
goto error;
/* Decode signature algorithm and hash algorithm */
err = sDecodeAlgorithmOID (asnctx, &cert->signatureAlgorithm.algorithm,
&sigalg, &hashalg);
if( IsPGPError(err) )
goto error;
/* Calculate length of signature */
certlen = pgpasn_SizeofCertificate( asnctx, cert, TRUE ) + 4;
certlenlen = (certlen < 192) ? 1 : 2;
extralen = validitylen + siglevellen + keyusagelen
+ certlen + certlenlen;
siglen = 8 + extralen + 2 + 3;
if( IsNull( sigBuf ) ) {
*sigLength = siglen;
return kPGPError_NoErr;
}
pgpAssert (*sigLength = siglen);
/* Lay out signature packet */
o = 0;
sigBuf[o++] = PGPVERSION_4;
sigBuf[o++] = PGP_SIGTYPE_KEY_GENERIC;
if (loversion <= 3)
sigBuf[o++] = 0; /* Use sigalgorithm of 0 because nonstandard */
else
sigBuf[o++] = 100; /* 100 is more compatible with OpenPGP */
sigBuf[o++] = hashalg; /* But use true hash algorithm */
sigBuf[o++] = (PGPByte) (extralen >> 8);
sigBuf[o++] = (PGPByte) (extralen >> 0);
err = sDecodeValidity (asnctx, cert, sigBuf + o, &validitylen);
o += validitylen;
err = sDecodeSigLevel (context, asnctx, cert, sigBuf + o, &siglevellen);
o += siglevellen;
err = sDecodeKeyUsage (asnctx, cert, sigBuf + o, &keyusagelen);
o += keyusagelen;
if (certlenlen == 1)
sigBuf[o++] = certlen;
else {
sigBuf[o++] = (PGPByte) (192 + ((certlen-192) >> 8));
sigBuf[o++] = (PGPByte) (certlen-192);
}
sigBuf[o++] = SIGSUB_NAI;
sigBuf[o++] = SIGSUBSUB_X509;
/* Store translation version bytes */
sigBuf[o++] = SIGSUBSUB_X509_VERSION_HI;
sigBuf[o++] = loversion;
pgpasn_PackCertificate( asnctx, sigBuf+o, certlen-4, cert, &err );
CHKASNERR( err );
o += certlen - 4;
/* No non-hashed data (yet) */
sigBuf[o++] = 0;
sigBuf[o++] = 0;
/* End up with dummy 2-byte checksum and dummy MPI for old parsers */
sigBuf[o++] = 0;
sigBuf[o++] = 0;
sigBuf[o++] = 0;
sigBuf[o++] = 1;
sigBuf[o++] = 1;
pgpAssert (o == siglen);
error:
return err;
}
/*
* Convert from X.509 cert to PGP style name. If issuer is true, we do
* issuer's name, else subject name.
* If namebuf is NULL, set *namelength to the necessary length. Else
* store the data into namebuf, and treat *namelength as an input parameter
* telling what the length needs to be.
* This versions uses long form for X509 names, in RFC2253 format.
*/
static PGPError
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -