📄 pgpx509keys.c
字号:
sDecodeNameLong(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
PGPBoolean issuer, PGPByte *nameBuf, PGPSize *nameLength)
{
PGPASN_Name *cname;
PGPASN_RDNSequence *name;
PGPASN_RelativeDistinguishedName *rdn;
PGPASN_AttributeTypeAndValue *atv;
PGPASN_DirectoryString *dstr;
PGPASN_VariableBlock *vb;
PGPBoolean sizingPass;
PGPBoolean seenName = FALSE;
PGPError err = kPGPError_NoErr;
char const *oidName;
PGPUInt32 lNameLength;
PGPUInt32 oidLength = 0;
PGPInt32 i, j;
PGPInt32 twice;
static char const dfltname[] = "(Unknown X509 name)";
sizingPass = (nameBuf==NULL);
lNameLength = sizingPass ? 0 : *nameLength;
cname = issuer ? &cert->tbsCertificate.issuer
: &cert->tbsCertificate.subject;
name = (PGPASN_RDNSequence *)cname->data;
/* Make two passes, doing common name last so it shows first */
for (twice=0; twice<2; ++twice) {
/* Loop over elements of RDN sequence */
for (i=0; i<name->n; ++i) {
rdn = name->elt[i];
for (j=0; j<rdn->n; ++j) {
atv = rdn->elt[j];
oidName = NULL;
if (atv->type.len == 3
&& atv->type.val[0] == cnoid[0]
&& atv->type.val[1] == cnoid[1]
&& atv->type.val[2] < sizeof(dnnames)/sizeof(dnnames[0])) {
/* Do CN if and only if twice==1 */
if ((atv->type.val[2] == cnoid[2]) == twice) {
oidName = dnnames[atv->type.val[2]];
oidLength = strlen(oidName);
}
}
else if (atv->type.len == sizeof(emailoid)
&& memcmp(atv->type.val, emailoid, atv->type.len)==0 ) {
if (!twice) {
oidName = emailname;
oidLength = strlen(oidName);
}
}
if( IsntNull( oidName ) ) {
/* Look at string for value */
pgpasn_UnpackDirectoryString( asnctx, &dstr,
atv->value.val, atv->value.len, &err );
if (err != 0) {
/* Skip if unprintable string */
err = 0;
continue;
}
vb = dstr->data;
/* Skip our inserted PGPKeyCreation string */
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)) {
if (vb->len == sizeof(s_pgpdescr)-1 + 8 &&
pgpMemoryEqual (vb->val, s_pgpdescr,
sizeof(s_pgpdescr)-1) ) {
pgpasn_FreeDirectoryString( asnctx, dstr );
continue;
}
}
seenName = TRUE;
if (sizingPass) {
/* add 3 for equals, comma, space */
lNameLength += strlen(oidName) + 3;
lNameLength += sDNQuoteString(vb->val, vb->len,
NULL, TRUE);
} else {
/* Build name string in reverse order, per LDAP */
lNameLength -= sDNQuoteString(vb->val, vb->len,
nameBuf+lNameLength, TRUE);
nameBuf[--lNameLength] = '=';
lNameLength -= oidLength;
pgpCopyMemory( oidName, nameBuf+lNameLength,
oidLength );
if( lNameLength > 0 ) {
nameBuf[--lNameLength] = ' ';
nameBuf[--lNameLength] = ',';
}
}
pgpasn_FreeDirectoryString( asnctx, dstr );
}
}
}
}
if( sizingPass ) {
if (lNameLength == 0) {
/* No name fields we recognized */
*nameLength = sizeof(dfltname);
} else {
lNameLength -= 2; /* Counted an initial ", " */
*nameLength = lNameLength;
}
} else {
/* lNameLength should have counted down to zero */
if( !seenName ) {
pgpAssert (lNameLength == sizeof(dfltname));
pgpCopyMemory (dfltname, nameBuf, lNameLength);
} else {
pgpAssert (lNameLength == 0);
}
}
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 version uses short form for X509 names, in PGP format.
* E.g. just "John Doe <john@doe.com>". If it can't be converted in that
* form, it uses the long form ("C=US, etc.").
*/
static PGPError
sDecodeName(PGPASN_CONTEXT *asnctx, PGPASN_Certificate *cert,
PGPBoolean issuer, PGPByte *nameBuf, PGPSize *nameLength)
{
#if !PGP_X509SHORTNAMES
return sDecodeNameLong(asnctx, cert, issuer, nameBuf, nameLength);
#else /* PGP_X509SHORTNAMES */
PGPASN_Name *cname;
PGPASN_RDNSequence *name;
PGPASN_RelativeDistinguishedName *rdn;
PGPASN_AttributeTypeAndValue *atv;
PGPASN_DirectoryString *dstr;
PGPASN_GeneralNames *gnames;
PGPASN_GeneralName *gname;
PGPASN_VariableBlock *vb;
PGPASN_Extensions *exts = cert->tbsCertificate.extensions;
PGPASN_Extension *ext;
PGPByte const *altnameoid;
PGPBoolean sizingPass;
PGPBoolean seenName = FALSE;
PGPBoolean seenEmail = FALSE;
PGPUInt32 lNameLength;
PGPInt32 i, j;
PGPError err = kPGPError_NoErr;
sizingPass = (nameBuf==NULL);
lNameLength = sizingPass ? 0 : *nameLength;
cname = issuer ? &cert->tbsCertificate.issuer
: &cert->tbsCertificate.subject;
name = (PGPASN_RDNSequence *)cname->data;
/* Loop over elements of RDN sequence until seen email and name */
for (i=0; (i<name->n) && !(seenEmail && seenName); ++i) {
rdn = name->elt[i];
for (j=0; (j<rdn->n) && !(seenEmail && seenName); ++j) {
atv = rdn->elt[j];
/* Parse attribute type */
if (atv->type.len == sizeof(cnoid)
&& memcmp(atv->type.val, cnoid, atv->type.len)==0 ) {
/* Common name, followed by a string */
pgpasn_UnpackDirectoryString( asnctx, &dstr, atv->value.val,
atv->value.len, &err );
if (err != 0) {
/* Skip if unprintable string */
err = 0;
continue;
}
vb = dstr->data;
seenName = TRUE;
if (sizingPass) {
lNameLength += vb->len;
} else {
/* Put common name at beginning of buffer */
pgpAssert (lNameLength >= vb->len);
pgpCopyMemory (vb->val, nameBuf, vb->len);
/* Add a space if needed */
if (lNameLength > vb->len)
nameBuf[vb->len] = ' ';
}
pgpasn_FreeDirectoryString( asnctx, dstr );
} else if (atv->type.len == sizeof(emailoid)
&& memcmp(atv->type.val, emailoid, atv->type.len)==0 ) {
/* Email address, followed by a string */
pgpasn_UnpackDirectoryString( asnctx, &dstr, atv->value.val,
atv->value.len, &err );
if (err != 0) {
/* Skip if unprintable string */
err = 0;
continue;
}
vb = dstr->data;
seenEmail = TRUE;
if (sizingPass) {
/* Add 2 for angle brackets */
lNameLength += vb->len + 2;
} else {
/* Put email address at end of buffer */
pgpAssert (lNameLength >= vb->len+2);
nameBuf[lNameLength-1] = '>';
pgpCopyMemory (vb->val, nameBuf+lNameLength-1-vb->len,
vb->len);
nameBuf[lNameLength-vb->len-2] = '<';
}
pgpasn_FreeDirectoryString( asnctx, dstr );
}
}
}
/* Check extensions to see if email is there, if not found yet */
if (seenName && !seenEmail && IsntNull(exts)) {
for (i=0; (i<exts->n) && !seenEmail; ++i) {
ext = exts->elt[i];
altnameoid = issuer ? issaltnameoid : subaltnameoid;
/* These are same size */
if (ext->extnID.len == sizeof(issaltnameoid)
&& memcmp(ext->extnID.val, altnameoid, ext->extnID.len)==0 ) {
/* Alternative name, just as we wanted */
pgpasn_UnpackGeneralNames( asnctx, &gnames, ext->extnValue.val,
ext->extnValue.len, &err );
if (err != 0) {
/* Skip if unprintable string */
err = 0;
continue;
}
for (j=0; (j<gnames->n) && !seenEmail; ++j) {
gname = gnames->elt[j];
if (gname->CHOICE_field_type != ASN_GENERALNAME_RFC822NAME)
continue;
/* Okay, we have an email address */
vb = gname->data;
seenEmail = TRUE;
if (sizingPass) {
/* Add 2 for angle brackets */
lNameLength += vb->len + 2;
} else {
/* Put email address at end of buffer */
pgpAssert (lNameLength >= vb->len+2);
nameBuf[lNameLength-1] = '>';
pgpCopyMemory (vb->val, nameBuf+lNameLength-1-vb->len,
vb->len);
nameBuf[lNameLength-vb->len-2] = '<';
}
}
pgpasn_FreeGeneralNames( asnctx, gnames );
}
}
}
if (!seenName || !seenEmail) {
/* If we could not parse the name, use the long form */
return sDecodeNameLong(asnctx, cert, issuer, nameBuf, nameLength);
}
if( sizingPass ) {
/* Count a space between name and email if have both */
if (seenName && seenEmail)
++lNameLength;
*nameLength = lNameLength;
}
return err;
#endif /* PGP_X509SHORTNAMES */
}
/*
* Create a PGP public key packet corresponding to the certificate, or a
* private key packet corresponding to the PrivateKeyInfo. Only one of
* these two pointers should be non-NULL.
*
* If keybuf is NULL, set *keylength to the necessary length. Else
* store the data into keybuf, and treat *keylength as an input parameter
* telling what the length needs to be.
*/
static PGPError
sDecodeKey(PGPContextRef context, PGPASN_CONTEXT *asnctx,
PGPASN_Certificate *cert, PGPASN_PrivateKeyInfo *pinfo,
PGPByte *keyBuf, PGPSize *keyLength)
{
PGPASN_SubjectPublicKeyInfo *spki =
&cert->tbsCertificate.subjectPublicKeyInfo;
PGPASN_DssParms *dssp = NULL;
PGPASN_DSAPublicKey *dssk = NULL;
PGPASN_ELGParms *elgp = NULL;
PGPASN_ELGPublicKey *elgk = NULL;
PGPASN_RSAKey *rsak = NULL;
PGPASN_PrivateKey *pkey;
PGPASN_RSAPrivateKey *rsapriv = NULL;
PGPPublicKeyAlgorithm keyalgorithm;
PGPByte *bnbuf[6]; /* buf offset for start of X.509 bignum */
PGPSize bnlen[6]; /* buf length for X.509 bignum */
PGPSize bnlength[6]; /* length of PGP encoded bignum */
PGPUInt32 pubelems=0; /* Number of bignum elements that are public */
PGPUInt32 i, j, o;
PGPUInt16 checksum;
PGPSize keybuflength;
PGPByte *pubbuf = NULL;
PGPSize publength;
PGPByte keyversion;
PGPByte const *matchkeybuf = NULL;
PGPSize matchkeybuflength;
RingObject *matchkey;
PGPMemoryMgrRef mgr = PGPGetContextMemoryMgr( context );
RingPool *pool = pgpContextGetRingPool( context );
PGPByte hash20[20];
PGPError err = kPGPError_NoErr;
/* Init bignum arrays */
pgpClearMemory (bnbuf, sizeof(bnbuf));
pgpClearMemory (bnlen, sizeof(bnlen));
pgpClearMemory (bnlength, sizeof(bnlength));
if (IsntNull( pinfo ) ) {
/* Do private key */
/* Decode object identifier for RSA/DSS/ElGamal */
err = sDecodeAlgorithmOID ( asnctx,
&pinfo->privateKeyAlgorithm.algorithm,
&keyalgorithm, NULL );
if( IsPGPError(err) )
goto error;
if (keyalgorithm == kPGPPublicKeyAlgorithm_RSA) {
pkey = &pinfo->privateKey;
pgpasn_UnpackRSAPrivateKey( asnctx, &rsapriv,
pkey->val, pkey->len, &err);
CHKASNERR(err);
/* modulus n */
bnbuf[0] = rsapriv->modulus.val;
bnlen[0] = rsapriv->modulus.len;
err = sDecodeX509Integer (bnbuf[0], bnlen[0], NULL, &bnlength[0]);
if( IsPGPError( err ) )
goto error;
/* public exponent e */
bnbuf[1] = rsapriv->publicExponent.val;
bnlen[1] = rsapriv->publicExponent.len;
err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
if( IsPGPError( err ) )
goto error;
/* private exponent d */
bnbuf[2] = rsapriv->privateExponent.val;
bnlen[2] = rsapriv->privateExponent.len;
err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
if( IsPGPError( err ) )
goto error;
/* smaller prime */
bnbuf[3] = rsapriv->prime2.val;
bnlen[3] = rsapriv->prime2.len;
err = sDecodeX509Integer (bnbuf[3], bnlen[3], NULL, &bnlength[3]);
if( IsPGPError( err ) )
goto error;
/* larger prime */
bnbuf[4] = rsapriv->prime1.val;
bnlen[4] = rsapriv->prime1.len;
err = sDecodeX509Integer (bnbuf[4], bnlen[4], NULL, &bnlength[4]);
if( IsPGPError( err ) )
goto error;
/* inverse u of smaller prime mod larger prime */
bnbuf[5] = rsapriv->coefficient.val;
bnlen[5] = rsapriv->coefficient.len;
err = sDecodeX509Integer (bnbuf[5], bnlen[5], NULL, &bnlength[5]);
if( IsPGPError( err ) )
goto error;
/* Number of these values which are public */
pubelems = 2;
} else if (keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
pgpAssert (0);
} else /* DSS */ {
pgpAssert (0);
}
} else {
/* Do public key */
/* Decode object identifier for RSA/DSS/ElGamal */
err = sDecodeAlgorithmOID ( asnctx, &spki->algorithm.algorithm,
&keyalgorithm, NULL );
if( IsPGPError(err) )
goto error;
if (keyalgorithm == kPGPPublicKeyAlgorithm_DSA) {
pgpasn_UnpackDssParms ( asnctx, &dssp,
spki->algorithm.parameters->val,
spki->algorithm.parameters->len, &err );
CHKASNERR( err );
pgpasn_UnpackDSAPublicKey ( asnctx, &dssk,
spki->subjectPublicKey.val,
spki->subjectPublicKey.len, &err );
CHKASNERR( err );
/* prime p */
bnbuf[0] = dssp->p.val;
bnlen[0] = dssp->p.len;
err = sDecodeX509Integer (bnbuf[0], bnlen[0], NULL, &bnlength[0]);
if( IsPGPError( err ) )
goto error;
/* subprime q */
bnbuf[1] = dssp->q.val;
bnlen[1] = dssp->q.len;
err = sDecodeX509Integer (bnbuf[1], bnlen[1], NULL, &bnlength[1]);
if( IsPGPError( err ) )
goto error;
/* generator g */
bnbuf[2] = dssp->g.val;
bnlen[2] = dssp->g.len;
err = sDecodeX509Integer (bnbuf[2], bnlen[2], NULL, &bnlength[2]);
if( IsPGPError( err ) )
goto error;
/* public value y */
bnbuf[3] = dssk->val;
bnlen[3] = dssk->len;
err = sDecodeX509Integer (bnbuf[3], bnlen[3], NULL, &bnlength[3]);
if( IsPGPError( err ) )
goto error;
pubelems = 4;
} else if (keyalgorithm == kPGPPublicKeyAlgorithm_ElGamal) {
pgpasn_UnpackELGParms ( asnctx, &elgp,
spki->algorithm.parameters->val,
spki->algorithm.parameters->len, &err );
CHKASNERR( err );
pgpasn_UnpackELGPublicKey ( asnctx, &elgk,
spki->subjectPublicKey.val,
spki->subjectPublicKey.len, &err );
CHKASNERR( err );
/* prime p */
bnbuf[0] = elgp->p.val;
bnlen[0] = elgp->p.len;
err = sDecodeX509Integer (bnbuf[0], bnlen[0], NULL, &bnlength[0]);
if( IsPGPError( err ) )
goto error;
/* generator g */
bnbuf[1] = elgp->g.val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -