Skip to content

Commit

Permalink
Implements basic support for V5 keys and signatures.
Browse files Browse the repository at this point in the history
  • Loading branch information
joke325 committed Apr 3, 2020
1 parent e102063 commit 4f42895
Show file tree
Hide file tree
Showing 14 changed files with 199 additions and 47 deletions.
4 changes: 3 additions & 1 deletion include/repgp/repgp_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@

/* Size of the fingerprint */
#define PGP_FINGERPRINT_SIZE 20
#define PGP_FINGERPRINT_MAX_SIZE 32
#define PGP_FINGERPRINT_HEX_SIZE (PGP_FINGERPRINT_SIZE * 3) + 1

/* Size of the key grip */
Expand Down Expand Up @@ -406,7 +407,8 @@ enum { PGP_SE_IP_DATA_VERSION = 1, PGP_PKSK_V3 = 3, PGP_SKSK_V4 = 4, PGP_SKSK_V5
typedef enum {
PGP_V2 = 2, /* Version 2 (essentially the same as v3) */
PGP_V3 = 3, /* Version 3 */
PGP_V4 = 4 /* Version 4 */
PGP_V4 = 4, /* Version 4 */
PGP_V5 = 5 /* Version 5 */
} pgp_version_t;

typedef enum pgp_op_t {
Expand Down
14 changes: 10 additions & 4 deletions src/lib/crypto/signatures.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,16 @@ signature_hash_finish(const pgp_signature_t *sig,
goto error;
}
if (sig->version > PGP_V3) {
uint8_t trailer[6] = {0x04, 0xff, 0x00, 0x00, 0x00, 0x00};
STORE32BE(&trailer[2], sig->hashed_len);

if (pgp_hash_add(hash, trailer, 6)) {
uint8_t trailer[10] = {0x04, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
size_t trail_size = 6;
if (sig->version == PGP_V5) {
trailer[0] = 0x05;
trail_size += 4;
STORE32BE(&trailer[6], sig->hashed_len);
} else {
STORE32BE(&trailer[2], sig->hashed_len);
}
if (pgp_hash_add(hash, trailer, trail_size)) {
RNP_LOG("failed to add sig trailer");
goto error;
}
Expand Down
6 changes: 3 additions & 3 deletions src/lib/ffi-priv-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,9 @@ struct rnp_identifier_iterator_st {
pgp_key_t * keyp;
unsigned uididx;
json_object * tbl;
char
buf[1 + MAX(MAX(MAX(PGP_KEY_ID_SIZE * 2, PGP_KEY_GRIP_SIZE), PGP_FINGERPRINT_SIZE * 2),
MAX_ID_LENGTH)];
char buf[1 + MAX(MAX(MAX(PGP_KEY_ID_SIZE * 2, PGP_KEY_GRIP_SIZE),
PGP_FINGERPRINT_MAX_SIZE * 2),
MAX_ID_LENGTH)];
};

/* This is just for readability at the call site and will hopefully reduce mistakes.
Expand Down
17 changes: 16 additions & 1 deletion src/lib/fingerprint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,19 @@ pgp_fingerprint(pgp_fingerprint_t *fp, const pgp_key_pkt_t *key)
return RNP_SUCCESS;
}

if (key->version == PGP_V5) {
if (!pgp_hash_create(&hash, PGP_HASH_SHA256)) {
RNP_LOG("bad sha256 alloc");
return RNP_ERROR_NOT_SUPPORTED;
}
if (!signature_hash_key(key, &hash)) {
return RNP_ERROR_GENERIC;
}
fp->length = pgp_hash_finish(&hash, fp->fingerprint);
RNP_DHEX("sha256 fingerprint", fp->fingerprint, fp->length);
return RNP_SUCCESS;
}

RNP_LOG("unsupported key version");
return RNP_ERROR_NOT_SUPPORTED;
}
Expand Down Expand Up @@ -102,7 +115,9 @@ pgp_keyid(uint8_t *keyid, const size_t idlen, const pgp_key_pkt_t *key)
if ((ret = pgp_fingerprint(&fp, key))) {
return ret;
}
(void) memcpy(keyid, fp.fingerprint + fp.length - idlen, idlen);

(void) memcpy(
keyid, fp.fingerprint + (key->version == PGP_V5 ? 0 : fp.length - idlen), idlen);
return RNP_SUCCESS;
}

Expand Down
12 changes: 8 additions & 4 deletions src/lib/rnp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ find_key(rnp_ffi_t ffi,
}
if (!key && ffi->getkeycb && try_key_provider) {
char identifier[1 + MAX(MAX(MAX(PGP_KEY_ID_SIZE * 2, PGP_KEY_GRIP_SIZE),
PGP_FINGERPRINT_SIZE * 2),
PGP_FINGERPRINT_MAX_SIZE * 2),
MAX_ID_LENGTH)];
const char *identifier_type = NULL;

Expand Down Expand Up @@ -2936,12 +2936,16 @@ str_to_locator(rnp_ffi_t ffi,
} break;
case PGP_KEY_SEARCH_FINGERPRINT: {
// TODO: support v5 fingerprints
if (strlen(identifier) != (PGP_FINGERPRINT_SIZE * 2)) {
switch (strlen(identifier)) {
case PGP_FINGERPRINT_SIZE * 2:
case PGP_FINGERPRINT_MAX_SIZE * 2:
break;
default:
FFI_LOG(ffi, "Invalid fingerprint: %s", identifier);
return RNP_ERROR_BAD_PARAMETERS;
}
locator->by.fingerprint.length = rnp_hex_decode(
identifier, locator->by.fingerprint.fingerprint, PGP_FINGERPRINT_SIZE);
identifier, locator->by.fingerprint.fingerprint, PGP_FINGERPRINT_MAX_SIZE);
if (!locator->by.fingerprint.length) {
FFI_LOG(ffi, "Invalid fingerprint: %s", identifier);
return RNP_ERROR_BAD_PARAMETERS;
Expand Down Expand Up @@ -6181,7 +6185,7 @@ key_to_json(json_object *jso, rnp_key_handle_t handle, uint32_t flags)
return RNP_ERROR_OUT_OF_MEMORY;
}
// fingerprint
char fpr[PGP_FINGERPRINT_SIZE * 2 + 1];
char fpr[PGP_FINGERPRINT_MAX_SIZE * 2 + 1];
if (!rnp_hex_encode(pgp_key_get_fp(key)->fingerprint,
pgp_key_get_fp(key)->length,
fpr,
Expand Down
2 changes: 1 addition & 1 deletion src/lib/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ typedef uint8_t pgp_ss_rr_code_t;

/** pgp_fingerprint_t */
typedef struct pgp_fingerprint_t {
uint8_t fingerprint[PGP_FINGERPRINT_SIZE];
uint8_t fingerprint[PGP_FINGERPRINT_MAX_SIZE];
unsigned length;
} pgp_fingerprint_t;

Expand Down
7 changes: 5 additions & 2 deletions src/librekey/key_store_kbx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,7 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest
bool result = false;
list subkey_sig_expirations = NULL; // expirations (uint32_t) of subkey signatures
uint32_t expiration = 0;
const pgp_fingerprint_t *fp;

if (init_mem_dest(&memdst, NULL, BLOB_SIZE_LIMIT)) {
RNP_LOG("alloc failed");
Expand Down Expand Up @@ -546,7 +547,8 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest
goto finish;
}

if (!pbuf(&memdst, pgp_key_get_fp(key)->fingerprint, PGP_FINGERPRINT_SIZE) ||
fp = pgp_key_get_fp(key);
if (!pbuf(&memdst, fp->fingerprint, fp->length) ||
!pu32(&memdst, memdst.writeb - 8) || // offset to keyid (part of fpr for V4)
!pu16(&memdst, 0) || // flags, not used by GnuPG
!pu16(&memdst, 0)) { // RFU
Expand All @@ -557,7 +559,8 @@ rnp_key_store_kbx_write_pgp(rnp_key_store_t *key_store, pgp_key_t *key, pgp_dest
for (list_item *sgrip = list_front(key->subkey_grips); sgrip; sgrip = list_next(sgrip)) {
const pgp_key_t *subkey =
rnp_key_store_get_key_by_grip(key_store, (const uint8_t *) sgrip);
if (!pbuf(&memdst, pgp_key_get_fp(subkey)->fingerprint, PGP_FINGERPRINT_SIZE) ||
fp = pgp_key_get_fp(subkey);
if (!pbuf(&memdst, fp->fingerprint, fp->length) ||
!pu32(&memdst, memdst.writeb - 8) || // offset to keyid (part of fpr for V4)
!pu16(&memdst, 0) || // flags, not used by GnuPG
!pu16(&memdst, 0)) { // RFU
Expand Down
7 changes: 3 additions & 4 deletions src/librepgp/stream-dump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,7 @@ signature_dump_subpacket(rnp_dump_ctx_t *ctx, pgp_dest_t *dst, pgp_sig_subpkt_t
dst_printf(dst, "%s\n", sname);
dst_printf(dst, "class: %d\n", (int) subpkt->fields.revocation_key.klass);
dst_print_palg(dst, NULL, subpkt->fields.revocation_key.pkalg);
dst_print_hex(
dst, "fingerprint", subpkt->fields.revocation_key.fp, PGP_FINGERPRINT_SIZE, true);
dst_print_hex(dst, "fingerprint", subpkt->fields.revocation_key.fp, subpkt->len, true);
break;
case PGP_SIG_SUBPKT_ISSUER_KEY_ID:
dst_print_keyid(dst, sname, subpkt->fields.issuer);
Expand Down Expand Up @@ -852,7 +851,7 @@ stream_dump_key(rnp_dump_ctx_t *ctx, pgp_source_t *src, pgp_dest_t *dst)

if (ctx->dump_grips) {
if (rnp_key_store_get_key_grip(&key.material, keyfp.fingerprint)) {
dst_print_hex(dst, "grip", keyfp.fingerprint, PGP_FINGERPRINT_SIZE, false);
dst_print_hex(dst, "grip", keyfp.fingerprint, keyfp.length, false);
} else {
dst_printf(dst, "grip: failed to calculate");
}
Expand Down Expand Up @@ -1481,7 +1480,7 @@ signature_dump_subpacket_json(rnp_dump_ctx_t *ctx, pgp_sig_subpkt_t *subpkt, jso
obj_add_field_json(
obj, "algorithm", json_object_new_int(subpkt->fields.revocation_key.pkalg)) &&
obj_add_hex_json(
obj, "fingerprint", subpkt->fields.revocation_key.fp, PGP_FINGERPRINT_SIZE);
obj, "fingerprint", subpkt->fields.revocation_key.fp, subpkt->len);
case PGP_SIG_SUBPKT_ISSUER_KEY_ID:
return obj_add_hex_json(obj, "issuer keyid", subpkt->fields.issuer, PGP_KEY_ID_SIZE);
case PGP_SIG_SUBPKT_KEYSERV_PREFS:
Expand Down
2 changes: 2 additions & 0 deletions src/librepgp/stream-key.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1274,6 +1274,8 @@ decrypt_secret_key(pgp_key_pkt_t *key, const char *password)
}
ret = decrypt_secret_key_v3(&crypt, decdata, key->sec_data, key->sec_len);
break;
case PGP_V5:
/* FALLTHROUGH */
case PGP_V4:
pgp_cipher_cfb_decrypt(&crypt, decdata, key->sec_data, key->sec_len);
ret = RNP_SUCCESS;
Expand Down
Loading

0 comments on commit 4f42895

Please sign in to comment.