/* Run the selftests for pubkey algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec; gcry_pk_spec_t *spec; algo = map_algo (algo); spec = spec_from_algo (algo); if (spec && !spec->flags.disabled && spec->selftest) ec = spec->selftest (algo, extended, report); else { ec = GPG_ERR_PUBKEY_ALGO; /* Fixme: We need to change the report fucntion to allow passing of an encryption mode (e.g. pkcs1, ecdsa, or ecdh). */ if (report) report ("pubkey", algo, "module", spec && !spec->flags.disabled? "no selftest available" : spec? "algorithm disabled" : "algorithm not found"); } return gpg_error (ec); }
/* Return the spec structure for the cipher algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_cipher_spec_t * spec_from_algo (int algo) { int idx; gcry_cipher_spec_t *spec; algo = map_algo (algo); for (idx = 0; (spec = cipher_list[idx]); idx++) if (algo == spec->algo) return spec; return NULL; }
gcry_sexp_t _gcry_pk_get_param (int algo, const char *name) { gcry_sexp_t result = NULL; gcry_pk_spec_t *spec = NULL; algo = map_algo (algo); if (algo != GCRY_PK_ECC) return NULL; spec = spec_from_name ("ecc"); if (spec) { if (spec && spec->get_curve_param) result = spec->get_curve_param (name); } return result; }
static int parse_signature_packet(signature_packet_t *p_sig, const uint8_t *p_buf, size_t i_packet_len) { if (!i_packet_len) /* 1st sanity check, we need at least the version */ return -1; p_sig->version = *p_buf++; size_t i_read; switch (p_sig->version) { case 3: i_read = parse_signature_v3_packet(p_sig, p_buf, i_packet_len); break; case 4: p_sig->specific.v4.hashed_data = nullptr; p_sig->specific.v4.unhashed_data = nullptr; i_read = parse_signature_v4_packet(p_sig, p_buf, i_packet_len); break; default: return -1; } if (i_read == 0) /* signature packet parsing has failed */ goto error; if (!map_algo(p_sig->public_key_algo)) goto error; if (!map_digestalgo(p_sig->digest_algo)) goto error; switch (p_sig->type) { case BINARY_SIGNATURE: case TEXT_SIGNATURE: case GENERIC_KEY_SIGNATURE: case PERSONA_KEY_SIGNATURE: case CASUAL_KEY_SIGNATURE: case POSITIVE_KEY_SIGNATURE: break; default: goto error; } p_buf--; /* rewind to the version byte */ p_buf += i_read; if (p_sig->public_key_algo == PUBLIC_KEY_ALGO_DSA) { READ_MPI(p_sig->algo_specific.dsa.r, 160); READ_MPI(p_sig->algo_specific.dsa.s, 160); } else if (p_sig->public_key_algo == PUBLIC_KEY_ALGO_RSA) READ_MPI(p_sig->algo_specific.rsa.s, 4096); else goto error; if (i_read != i_packet_len) goto error; return 0; error: if (p_sig->version == 4) { free(p_sig->specific.v4.hashed_data); free(p_sig->specific.v4.unhashed_data); } return -1; }
/* * fill a signature_packet_v4_t from signature packet data * verify that it was used with a DSA or RSA public key */ static size_t parse_signature_v4_packet(signature_packet_t *p_sig, const uint8_t *p_buf, size_t i_sig_len) { size_t i_read = 1; /* we already read the version byte */ if (i_sig_len < 10) /* signature is at least 10 bytes + the 2 MPIs */ return 0; p_sig->type = *p_buf++; i_read++; p_sig->public_key_algo = *p_buf++; i_read++; p_sig->digest_algo = *p_buf++; i_read++; if (!map_algo(p_sig->public_key_algo)) return 0; memcpy(p_sig->specific.v4.hashed_data_len, p_buf, 2); p_buf += 2; i_read += 2; size_t i_hashed_data_len = scalar_number(p_sig->specific.v4.hashed_data_len, 2); i_read += i_hashed_data_len; if (i_read + 4 > i_sig_len || i_hashed_data_len > i_sig_len) return 0; p_sig->specific.v4.hashed_data = (uint8_t*) malloc(i_hashed_data_len); if (!p_sig->specific.v4.hashed_data) return 0; memcpy(p_sig->specific.v4.hashed_data, p_buf, i_hashed_data_len); p_buf += i_hashed_data_len; memcpy(p_sig->specific.v4.unhashed_data_len, p_buf, 2); p_buf += 2; i_read += 2; size_t i_unhashed_data_len = scalar_number(p_sig->specific.v4.unhashed_data_len, 2); i_read += i_unhashed_data_len; if (i_read + 2 > i_sig_len || i_unhashed_data_len > i_sig_len) return 0; p_sig->specific.v4.unhashed_data = (uint8_t*) malloc(i_unhashed_data_len); if (!p_sig->specific.v4.unhashed_data) return 0; memcpy(p_sig->specific.v4.unhashed_data, p_buf, i_unhashed_data_len); p_buf += i_unhashed_data_len; memcpy(p_sig->hash_verification, p_buf, 2); p_buf += 2; i_read += 2; uint8_t *p, *max_pos; p = p_sig->specific.v4.unhashed_data; max_pos = p + i_unhashed_data_len; for (;;) { if (p > max_pos) return 0; size_t i_subpacket_len; if (*p < 192) { if (p + 1 > max_pos) return 0; i_subpacket_len = *p++; } else if (*p < 255) { if (p + 2 > max_pos) return 0; i_subpacket_len = (*p++ - 192) << 8; i_subpacket_len += *p++ + 192; } else { if (p + 4 > max_pos) return 0; i_subpacket_len = size_t(*++p) << 24; i_subpacket_len += *++p << 16; i_subpacket_len += *++p << 8; i_subpacket_len += *++p; } if (*p == ISSUER_SUBPACKET) { if (p + 9 > max_pos) return 0; memcpy(&p_sig->issuer_longid, p + 1, 8); return i_read; } if (i_subpacket_len > i_unhashed_data_len) return 0; p += i_subpacket_len; } }