On Sat, Nov 03, 2012 at 01:28:17AM +1000, Allan McRae wrote: > This does not support all possibilities of RFC4880, but it does > cover every key currently used in Arch Linux.
Hmmm, this function doesn't seem to distinguish between "not a key" and "not a supported key". Can we return more useful error codes, like -ENOSYS for unsupported, -EINVAL for not-a-signature packet... > Signed-off-by: Allan McRae <[email protected]> > --- > lib/libalpm/signing.c | 100 > ++++++++++++++++++++++++++++++++++++++++++++++++++ > lib/libalpm/signing.h | 2 + > 2 files changed, 102 insertions(+) > > diff --git a/lib/libalpm/signing.c b/lib/libalpm/signing.c > index 9d56aba..6b13522 100644 > --- a/lib/libalpm/signing.c > +++ b/lib/libalpm/signing.c > @@ -948,4 +948,104 @@ int SYMEXPORT alpm_siglist_cleanup(alpm_siglist_t > *siglist) > return 0; > } > > +/** > + * Extract the Issuer Key ID from a signature > + * @param sig PGP signature > + * @param len length of signature > + * @param keys a pointer to storage for key IDs > + * @return 0 on success, -1 on error > + */ > +int _alpm_extract_keyid(const unsigned char *sig, size_t len, alpm_list_t > **keys) > +{ > + size_t pos, spos, blen, hlen, ulen, slen; > + pos = 0; > + > + while(pos < len) { > + if(!(sig[pos] & 0x80)) { > + return -1; > + } > + > + if(sig[pos] & 0x40) { > + // "new" packet format is not supported > + return -1; > + } > + > + if(((sig[pos] & 0x3f) >> 2) != 2) { > + // signature is not a "Signature Packet" > + return -1; > + } > + > + switch (sig[pos] & 0x03) { style nit: switch(foo) > + case 0: > + blen = sig[pos + 1]; > + pos = pos + 2; > + break; > + > + case 1: > + blen = (sig[pos + 1] << 8) | sig[pos + 2]; > + pos = pos + 3; > + break; > + > + case 2: > + blen = (sig[pos + 1] << 24) | (sig[pos + 2] << > 16) | (sig[pos + 3] << 8) | sig[pos + 4]; > + pos = pos + 5; > + break; > + > + case 3: > + // partial body length not supported > + return -1; > + } > + > + if(sig[pos] != 4) { > + // only support version 4 signature packet format > + return -1; > + } > + > + if(sig[pos + 1] != 0x00) { > + // not a signature of a binary document > + return -1; > + } > + > + pos = pos + 4; > + > + hlen = (sig[pos] << 8) | sig[pos + 1]; > + pos = pos + hlen + 2; > + > + ulen = (sig[pos] << 8) | sig[pos + 1]; > + pos = pos + 2; > + > + spos = pos; > + > + while(spos < pos + ulen) { > + if(sig[spos] < 192) { > + slen = sig[spos]; > + spos = spos + 1; > + } else if(sig[spos] < 255) { > + slen = (sig[spos] << 8) | sig[spos + 1]; > + spos = spos + 2; > + } else { > + slen = (sig[spos + 1] << 24) | (sig[spos + 2] > << 16) | (sig[spos + 3] << 8) | sig[spos + 4]; > + spos = spos + 5; > + } > + > + if(sig[spos] == 16) { > + // issuer key ID > + char key[16]; > + size_t i; > + for (i = 0; i < 8; i++) { > + sprintf(&key[i * 2], "%02hhX", sig[spos > + i + 1]); > + } > + *keys = alpm_list_add(*keys, strdup(key)); Would be nice to be robust against strdup() memory allocation failures here. > + break; > + } > + > + spos = spos + slen; > + } > + > + pos = pos + (blen - hlen - 8); > + } > + > + return 0; > +} > + > /* vim: set ts=2 sw=2 noet: */ > diff --git a/lib/libalpm/signing.h b/lib/libalpm/signing.h > index a78e4b7..6537ee3 100644 > --- a/lib/libalpm/signing.h > +++ b/lib/libalpm/signing.h > @@ -34,6 +34,8 @@ int _alpm_process_siglist(alpm_handle_t *handle, const char > *identifier, > int _alpm_key_in_keychain(alpm_handle_t *handle, const char *fpr); > int _alpm_key_import(alpm_handle_t *handle, const char *fpr); > > +int _alpm_extract_keyid(const unsigned char *sig, size_t len, alpm_list_t > **keys); > + > #endif /* _ALPM_SIGNING_H */ > > /* vim: set ts=2 sw=2 noet: */ > -- > 1.8.0 > >
