summaryrefslogtreecommitdiff
path: root/rpmio/rpmpgp.c
diff options
context:
space:
mode:
authorwangbiao <biao716.wang@samsung.com>2023-11-16 18:17:42 +0900
committerwangbiao <biao716.wang@samsung.com>2023-11-16 18:17:42 +0900
commitc30d127e8780dc678168ee121b9f2eeb1a8aaafa (patch)
treecdc9ddc3123edd5741e5151f3076c9bfc9535916 /rpmio/rpmpgp.c
parent258ff2bdb80c458b743417c427f66fa5f27bf7c5 (diff)
downloadlibrpm-tizen-tizen/4.14.1.1.tizen20230628.tar.gz
librpm-tizen-tizen/4.14.1.1.tizen20230628.tar.bz2
librpm-tizen-tizen/4.14.1.1.tizen20230628.zip
Upgrade version to 4.14tizen/4.14.1.1.tizen20230628
Change-Id: I21bf1a3a7c25cbec43022202cf2e5865b603a309 Signed-off-by: wangbiao <biao716.wang@samsung.com>
Diffstat (limited to 'rpmio/rpmpgp.c')
-rw-r--r--rpmio/rpmpgp.c370
1 files changed, 302 insertions, 68 deletions
diff --git a/rpmio/rpmpgp.c b/rpmio/rpmpgp.c
index e70cf706b..15cce2275 100644
--- a/rpmio/rpmpgp.c
+++ b/rpmio/rpmpgp.c
@@ -248,6 +248,19 @@ static void pgpPrtVal(const char * pre, pgpValTbl vs, uint8_t val)
fprintf(stderr, "%s(%u)", pgpValStr(vs, val), (unsigned)val);
}
+static void pgpPrtTime(const char * pre, const uint8_t *p, size_t plen)
+{
+ if (!_print) return;
+ if (pre && *pre)
+ fprintf(stderr, "%s", pre);
+ if (plen == 4) {
+ time_t t = pgpGrab(p, plen);
+ fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
+ } else {
+ pgpPrtHex("", p+1, plen-1);
+ }
+}
+
/** \ingroup rpmpgp
* Return hex formatted representation of a multiprecision integer.
* @param p bytes
@@ -384,15 +397,24 @@ unsigned int pgpCRC(const uint8_t *octets, size_t len)
return crc & 0xffffff;
}
+static int pgpVersion(const uint8_t *h, size_t hlen, uint8_t *version)
+{
+ if (hlen < 1)
+ return -1;
+
+ *version = h[0];
+ return 0;
+}
+
static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
pgpDigParams _digp)
{
const uint8_t *p = h;
- size_t plen, i;
+ size_t plen = 0, i;
while (hlen > 0) {
i = pgpLen(p, hlen, &plen);
- if (i == 0 || i + plen > hlen)
+ if (i == 0 || plen < 1 || i + plen > hlen)
break;
p += i;
@@ -423,23 +445,22 @@ static int pgpPrtSubType(const uint8_t *h, size_t hlen, pgpSigType sigtype,
if (!(_digp->saved & PGPDIG_SAVED_TIME) &&
(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
{
+ if (plen-1 != sizeof(_digp->time))
+ break;
_digp->saved |= PGPDIG_SAVED_TIME;
- memcpy(_digp->time, p+1, sizeof(_digp->time));
+ _digp->time = pgpGrab(p+1, sizeof(_digp->time));
}
case PGPSUBTYPE_SIG_EXPIRE_TIME:
case PGPSUBTYPE_KEY_EXPIRE_TIME:
- if ((plen - 1) == 4) {
- time_t t = pgpGrab(p+1, plen-1);
- if (_print)
- fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
- } else
- pgpPrtHex("", p+1, plen-1);
+ pgpPrtTime(" ", p+1, plen-1);
break;
case PGPSUBTYPE_ISSUER_KEYID: /* issuer key ID */
if (!(_digp->saved & PGPDIG_SAVED_ID) &&
(sigtype == PGPSIGTYPE_POSITIVE_CERT || sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT || sigtype == PGPSIGTYPE_STANDALONE))
{
+ if (plen-1 != sizeof(_digp->signid))
+ break;
_digp->saved |= PGPDIG_SAVED_ID;
memcpy(_digp->signid, p+1, sizeof(_digp->signid));
}
@@ -499,11 +520,15 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
int i;
pgpDigAlg sigalg = pgpSignatureNew(pubkey_algo);
- for (i = 0; p < pend && i < sigalg->mpis; i++, p += pgpMpiLen(p)) {
+ for (i = 0; i < sigalg->mpis && p + 2 <= pend; i++) {
+ int mpil = pgpMpiLen(p);
+ if (p + mpil > pend)
+ break;
if (sigtype == PGPSIGTYPE_BINARY || sigtype == PGPSIGTYPE_TEXT) {
- if (sigalg->setmpi(sigalg, i, p, pend))
+ if (sigalg->setmpi(sigalg, i, p))
break;
}
+ p += mpil;
}
/* Does the size and number of MPI's match our expectations? */
@@ -519,18 +544,33 @@ static int pgpPrtSigParams(pgpTag tag, uint8_t pubkey_algo, uint8_t sigtype,
return rc;
}
+static int pgpGet(const uint8_t *s, size_t nbytes, const uint8_t *send,
+ unsigned int *valp)
+{
+ int rc = -1;
+
+ if (s + nbytes <= send) {
+ *valp = pgpGrab(s, nbytes);
+ rc = 0;
+ }
+
+ return rc;
+}
+
static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
pgpDigParams _digp)
{
- uint8_t version = h[0];
+ uint8_t version = 0;
uint8_t * p;
- size_t plen;
- int rc;
+ unsigned int plen;
+ int rc = 1;
+
+ if (pgpVersion(h, hlen, &version))
+ return rc;
switch (version) {
case 3:
{ pgpPktSigV3 v = (pgpPktSigV3)h;
- time_t t;
if (hlen <= sizeof(*v) || v->hashlen != 5)
return 1;
@@ -540,9 +580,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
pgpPrtVal(" ", pgpHashTbl, v->hash_algo);
pgpPrtVal(" ", pgpSigTypeTbl, v->sigtype);
pgpPrtNL();
- t = pgpGrab(v->time, sizeof(v->time));
- if (_print)
- fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
+ pgpPrtTime(" ", v->time, sizeof(v->time));
pgpPrtNL();
pgpPrtHex(" signer keyid", v->signid, sizeof(v->signid));
plen = pgpGrab(v->signhash16, sizeof(v->signhash16));
@@ -554,7 +592,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
_digp->hashlen = v->hashlen;
_digp->sigtype = v->sigtype;
_digp->hash = memcpy(xmalloc(v->hashlen), &v->sigtype, v->hashlen);
- memcpy(_digp->time, v->time, sizeof(_digp->time));
+ _digp->time = pgpGrab(v->time, sizeof(v->time));
memcpy(_digp->signid, v->signid, sizeof(_digp->signid));
_digp->pubkey_algo = v->pubkey_algo;
_digp->hash_algo = v->hash_algo;
@@ -577,7 +615,8 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
pgpPrtNL();
p = &v->hashlen[0];
- plen = pgpGrab(v->hashlen, sizeof(v->hashlen));
+ if (pgpGet(v->hashlen, sizeof(v->hashlen), h + hlen, &plen))
+ return 1;
p += sizeof(v->hashlen);
if ((p + plen) > (h + hlen))
@@ -591,7 +630,8 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
return 1;
p += plen;
- plen = pgpGrab(p,2);
+ if (pgpGet(p, 2, h + hlen, &plen))
+ return 1;
p += 2;
if ((p + plen) > (h + hlen))
@@ -601,7 +641,8 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
return 1;
p += plen;
- plen = pgpGrab(p,2);
+ if (pgpGet(p, 2, h + hlen, &plen))
+ return 1;
pgpPrtHex(" signhash16", p, 2);
pgpPrtNL();
@@ -620,6 +661,7 @@ static int pgpPrtSig(pgpTag tag, const uint8_t *h, size_t hlen,
rc = pgpPrtSigParams(tag, v->pubkey_algo, v->sigtype, p, h, hlen, _digp);
} break;
default:
+ rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version);
rc = 1;
break;
}
@@ -650,9 +692,13 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo,
int i;
pgpDigAlg keyalg = pgpPubkeyNew(pubkey_algo);
- for (i = 0; p < pend && i < keyalg->mpis; i++, p += pgpMpiLen(p)) {
- if (keyalg->setmpi(keyalg, i, p, pend))
+ for (i = 0; i < keyalg->mpis && p + 2 <= pend; i++) {
+ int mpil = pgpMpiLen(p);
+ if (p + mpil > pend)
+ break;
+ if (keyalg->setmpi(keyalg, i, p))
break;
+ p += mpil;
}
/* Does the size and number of MPI's match our expectations? */
@@ -660,7 +706,9 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo,
rc = 0;
/* We can't handle more than one key at a time */
- if (rc == 0 && keyp->alg == NULL && keyp->tag == PGPTAG_PUBLIC_KEY)
+ if (rc == 0 && keyp->alg == NULL && (keyp->tag == PGPTAG_PUBLIC_KEY ||
+ keyp->tag == PGPTAG_PUBLIC_SUBKEY))
+
keyp->alg = keyalg;
else
pgpDigAlgFree(keyalg);
@@ -671,11 +719,13 @@ static int pgpPrtPubkeyParams(uint8_t pubkey_algo,
static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
pgpDigParams _digp)
{
- uint8_t version = *h;
+ uint8_t version = 0;
const uint8_t * p = NULL;
- time_t t;
int rc = 1;
+ if (pgpVersion(h, hlen, &version))
+ return rc;
+
/* We only permit V4 keys, V3 keys are long long since deprecated */
switch (version) {
case 4:
@@ -684,14 +734,13 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
if (hlen > sizeof(*v)) {
pgpPrtVal("V4 ", pgpTagTbl, tag);
pgpPrtVal(" ", pgpPubkeyTbl, v->pubkey_algo);
- t = pgpGrab(v->time, sizeof(v->time));
- if (_print)
- fprintf(stderr, " %-24.24s(0x%08x)", ctime(&t), (unsigned)t);
+ pgpPrtTime(" ", v->time, sizeof(v->time));
pgpPrtNL();
- if (_digp->tag == tag) {
+ /* If _digp->hash is not NULL then signature is already loaded */
+ if (_digp->hash == NULL) {
_digp->version = v->version;
- memcpy(_digp->time, v->time, sizeof(_digp->time));
+ _digp->time = pgpGrab(v->time, sizeof(v->time));
_digp->pubkey_algo = v->pubkey_algo;
}
@@ -699,6 +748,8 @@ static int pgpPrtKey(pgpTag tag, const uint8_t *h, size_t hlen,
rc = pgpPrtPubkeyParams(v->pubkey_algo, p, h, hlen, _digp);
}
} break;
+ default:
+ rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), h[0]);
}
return rc;
}
@@ -716,14 +767,19 @@ static int pgpPrtUserID(pgpTag tag, const uint8_t *h, size_t hlen,
return 0;
}
-static int getFingerprint(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
+int pgpPubkeyFingerprint(const uint8_t *h, size_t hlen,
+ uint8_t **fp, size_t *fplen)
{
int rc = -1; /* assume failure */
const uint8_t *se;
const uint8_t *pend = h + hlen;
+ uint8_t version = 0;
+
+ if (pgpVersion(h, hlen, &version))
+ return rc;
/* We only permit V4 keys, V3 keys are long long since deprecated */
- switch (h[0]) {
+ switch (version) {
case 4:
{ pgpPktKeyV4 v = (pgpPktKeyV4) (h);
int mpis = -1;
@@ -747,8 +803,8 @@ static int getFingerprint(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
/* Does the size and number of MPI's match our expectations? */
if (se == pend && mpis == 0) {
DIGEST_CTX ctx = rpmDigestInit(PGPHASHALGO_SHA1, RPMDIGEST_NONE);
- uint8_t * d = NULL;
- size_t dlen;
+ uint8_t *d = NULL;
+ size_t dlen = 0;
int i = se - h;
uint8_t in[3] = { 0x99, (i >> 8), i };
@@ -756,42 +812,42 @@ static int getFingerprint(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
(void) rpmDigestUpdate(ctx, h, i);
(void) rpmDigestFinal(ctx, (void **)&d, &dlen, 0);
- if (d) {
- memcpy(keyid, (d + (dlen-8)), 8);
- free(d);
+ if (dlen == 20) {
rc = 0;
+ *fp = d;
+ *fplen = dlen;
+ } else {
+ free(d);
}
}
} break;
+ default:
+ rpmlog(RPMLOG_WARNING, _("Unsupported version of key: V%d\n"), version);
+ }
+ return rc;
+}
+
+static int getKeyID(const uint8_t *h, size_t hlen, pgpKeyID_t keyid)
+{
+ uint8_t *fp = NULL;
+ size_t fplen = 0;
+ int rc = pgpPubkeyFingerprint(h, hlen, &fp, &fplen);
+ if (fp && fplen > 8) {
+ memcpy(keyid, (fp + (fplen-8)), 8);
+ free(fp);
}
return rc;
}
-int pgpPubkeyFingerprint(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
+int pgpPubkeyKeyID(const uint8_t * pkt, size_t pktlen, pgpKeyID_t keyid)
{
struct pgpPkt p;
if (decodePkt(pkt, pktlen, &p))
return -1;
- return getFingerprint(p.body, p.blen, keyid);
-}
-
-int pgpExtractPubkeyFingerprint(const char * b64pkt, pgpKeyID_t keyid)
-{
- uint8_t * pkt;
- size_t pktlen;
- int rc = -1; /* assume failure */
-
- if (rpmBase64Decode(b64pkt, (void **)&pkt, &pktlen) == 0) {
- if (pgpPubkeyFingerprint(pkt, pktlen, keyid) == 0) {
- /* if there ever was a bizarre return code for success... */
- rc = 8;
- }
- free(pkt);
- }
- return rc;
+ return getKeyID(p.body, p.blen, keyid);
}
static int pgpPrtPkt(struct pgpPkt *p, pgpDigParams _digp)
@@ -803,8 +859,8 @@ static int pgpPrtPkt(struct pgpPkt *p, pgpDigParams _digp)
rc = pgpPrtSig(p->tag, p->body, p->blen, _digp);
break;
case PGPTAG_PUBLIC_KEY:
- /* Get the public key fingerprint. */
- if (!getFingerprint(p->body, p->blen, _digp->signid))
+ /* Get the public key Key ID. */
+ if (!getKeyID(p->body, p->blen, _digp->signid))
_digp->saved |= PGPDIG_SAVED_ID;
else
memset(_digp->signid, 0, sizeof(_digp->signid));
@@ -813,12 +869,14 @@ static int pgpPrtPkt(struct pgpPkt *p, pgpDigParams _digp)
case PGPTAG_USER_ID:
rc = pgpPrtUserID(p->tag, p->body, p->blen, _digp);
break;
+ case PGPTAG_RESERVED:
+ rc = -1;
+ break;
case PGPTAG_COMMENT:
case PGPTAG_COMMENT_OLD:
case PGPTAG_PUBLIC_SUBKEY:
case PGPTAG_SECRET_KEY:
case PGPTAG_SECRET_SUBKEY:
- case PGPTAG_RESERVED:
case PGPTAG_PUBLIC_SESSION_KEY:
case PGPTAG_SYMMETRIC_SESSION_KEY:
case PGPTAG_COMPRESSED_DATA:
@@ -903,6 +961,8 @@ int pgpDigParamsCmp(pgpDigParams p1, pgpDigParams p2)
int rc = 1; /* assume different, eg if either is NULL */
if (p1 && p2) {
/* XXX Should we compare something else too? */
+ if (p1->tag != p2->tag)
+ goto exit;
if (p1->hash_algo != p2->hash_algo)
goto exit;
if (p1->pubkey_algo != p2->pubkey_algo)
@@ -913,6 +973,8 @@ int pgpDigParamsCmp(pgpDigParams p1, pgpDigParams p2)
goto exit;
if (memcmp(p1->signid, p2->signid, sizeof(p1->signid)) != 0)
goto exit;
+ if (p1->userid && p2->userid && strcmp(p1->userid, p2->userid) != 0)
+ goto exit;
/* Parameters match ... at least for our purposes */
rc = 0;
@@ -937,36 +999,128 @@ unsigned int pgpDigParamsAlgo(pgpDigParams digp, unsigned int algotype)
return algo;
}
+static pgpDigParams pgpDigParamsNew(uint8_t tag)
+{
+ pgpDigParams digp = xcalloc(1, sizeof(*digp));
+ digp->tag = tag;
+ return digp;
+}
+
+static int hashKey(DIGEST_CTX hash, const struct pgpPkt *pkt, int exptag)
+{
+ int rc = -1;
+ if (pkt->tag == exptag) {
+ uint8_t head[] = {
+ 0x99,
+ (pkt->blen >> 8),
+ (pkt->blen ),
+ };
+
+ rpmDigestUpdate(hash, head, 3);
+ rpmDigestUpdate(hash, pkt->body, pkt->blen);
+ rc = 0;
+ }
+ return rc;
+}
+
+static int pgpVerifySelf(pgpDigParams key, pgpDigParams selfsig,
+ const struct pgpPkt *all, int i)
+{
+ int rc = -1;
+ DIGEST_CTX hash = NULL;
+
+ switch (selfsig->sigtype) {
+ case PGPSIGTYPE_SUBKEY_BINDING:
+ hash = rpmDigestInit(selfsig->hash_algo, 0);
+ if (hash) {
+ rc = hashKey(hash, &all[0], PGPTAG_PUBLIC_KEY);
+ if (!rc)
+ rc = hashKey(hash, &all[i-1], PGPTAG_PUBLIC_SUBKEY);
+ }
+ break;
+ default:
+ /* ignore types we can't handle */
+ rc = 0;
+ break;
+ }
+
+ if (hash && rc == 0)
+ rc = pgpVerifySignature(key, selfsig, hash);
+
+ rpmDigestFinal(hash, NULL, NULL, 0);
+
+ return rc;
+}
+
int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
pgpDigParams * ret)
{
const uint8_t *p = pkts;
const uint8_t *pend = pkts + pktlen;
pgpDigParams digp = NULL;
- struct pgpPkt pkt;
+ pgpDigParams selfsig = NULL;
+ int i = 0;
+ int alloced = 16; /* plenty for normal cases */
+ struct pgpPkt *all = xmalloc(alloced * sizeof(*all));
int rc = -1; /* assume failure */
+ int expect = 0;
+ int prevtag = 0;
while (p < pend) {
- if (decodePkt(p, (pend - p), &pkt))
+ struct pgpPkt *pkt = &all[i];
+ if (decodePkt(p, (pend - p), pkt))
break;
if (digp == NULL) {
- if (pkttype && pkt.tag != pkttype) {
+ if (pkttype && pkt->tag != pkttype) {
break;
} else {
- digp = xcalloc(1, sizeof(*digp));
- digp->tag = pkt.tag;
+ digp = pgpDigParamsNew(pkt->tag);
}
}
- if (pgpPrtPkt(&pkt, digp))
+ if (expect) {
+ if (pkt->tag != expect)
+ break;
+ selfsig = pgpDigParamsNew(pkt->tag);
+ }
+
+ if (pgpPrtPkt(pkt, selfsig ? selfsig : digp))
break;
- p += (pkt.body - pkt.head) + pkt.blen;
+ if (selfsig) {
+ /* subkeys must be followed by binding signature */
+ if (prevtag == PGPTAG_PUBLIC_SUBKEY) {
+ if (selfsig->sigtype != PGPSIGTYPE_SUBKEY_BINDING)
+ break;
+ }
+
+ int xx = pgpVerifySelf(digp, selfsig, all, i);
+
+ selfsig = pgpDigParamsFree(selfsig);
+ if (xx)
+ break;
+ expect = 0;
+ }
+
+ if (pkt->tag == PGPTAG_PUBLIC_SUBKEY)
+ expect = PGPTAG_SIGNATURE;
+ prevtag = pkt->tag;
+
+ i++;
+ p += (pkt->body - pkt->head) + pkt->blen;
+ if (pkttype == PGPTAG_SIGNATURE)
+ break;
+
+ if (alloced <= i) {
+ alloced *= 2;
+ all = xrealloc(all, alloced * sizeof(*all));
+ }
}
- rc = (digp && (p == pend)) ? 0 : -1;
+ rc = (digp && (p == pend) && expect == 0) ? 0 : -1;
+ free(all);
if (ret && rc == 0) {
*ret = digp;
} else {
@@ -975,6 +1129,63 @@ int pgpPrtParams(const uint8_t * pkts, size_t pktlen, unsigned int pkttype,
return rc;
}
+int pgpPrtParamsSubkeys(const uint8_t *pkts, size_t pktlen,
+ pgpDigParams mainkey, pgpDigParams **subkeys,
+ int *subkeysCount)
+{
+ const uint8_t *p = pkts;
+ const uint8_t *pend = pkts + pktlen;
+ pgpDigParams *digps = NULL;
+ int count = 0;
+ int alloced = 10;
+ struct pgpPkt pkt;
+ int rc, i;
+
+ digps = xmalloc(alloced * sizeof(*digps));
+
+ while (p < pend) {
+ if (decodePkt(p, (pend - p), &pkt))
+ break;
+
+ p += (pkt.body - pkt.head) + pkt.blen;
+
+ if (pkt.tag == PGPTAG_PUBLIC_SUBKEY) {
+ if (count == alloced) {
+ alloced <<= 1;
+ digps = xrealloc(digps, alloced * sizeof(*digps));
+ }
+
+ digps[count] = xcalloc(1, sizeof(**digps));
+ digps[count]->tag = PGPTAG_PUBLIC_SUBKEY;
+ /* Copy UID from main key to subkey */
+ digps[count]->userid = xstrdup(mainkey->userid);
+
+ if (getKeyID(pkt.body, pkt.blen, digps[count]->signid)) {
+ pgpDigParamsFree(digps[count]);
+ continue;
+ }
+
+ if (pgpPrtKey(pkt.tag, pkt.body, pkt.blen, digps[count])) {
+ pgpDigParamsFree(digps[count]);
+ continue;
+ }
+ count++;
+ }
+ }
+ rc = (p == pend) ? 0 : -1;
+
+ if (rc == 0) {
+ *subkeys = xrealloc(digps, count * sizeof(*digps));
+ *subkeysCount = count;
+ } else {
+ for (i = 0; i < count; i++)
+ pgpDigParamsFree(digps[i]);
+ free(digps);
+ }
+
+ return rc;
+}
+
int pgpPrtPkts(const uint8_t * pkts, size_t pktlen, pgpDig dig, int printing)
{
int rc;
@@ -1230,6 +1441,29 @@ pgpArmor pgpParsePkts(const char *armor, uint8_t ** pkt, size_t * pktlen)
return ec;
}
+int pgpPubKeyCertLen(const uint8_t *pkts, size_t pktslen, size_t *certlen)
+{
+ const uint8_t *p = pkts;
+ const uint8_t *pend = pkts + pktslen;
+ struct pgpPkt pkt;
+
+ while (p < pend) {
+ if (decodePkt(p, (pend - p), &pkt))
+ return -1;
+
+ if (pkt.tag == PGPTAG_PUBLIC_KEY && pkts != p) {
+ *certlen = p - pkts;
+ return 0;
+ }
+
+ p += (pkt.body - pkt.head) + pkt.blen;
+ }
+
+ *certlen = pktslen;
+
+ return 0;
+}
+
char * pgpArmorWrap(int atype, const unsigned char * s, size_t ns)
{
char *buf = NULL, *val = NULL;