/* Put the DIGEST into an DER encoded container and return it in R_VAL. */ static int encode_md_for_card (const unsigned char *digest, size_t digestlen, int algo, unsigned char **r_val, size_t *r_len) { unsigned char *frame; unsigned char asn[100]; size_t asnlen; *r_val = NULL; *r_len = 0; asnlen = DIM(asn); if (!algo || gcry_md_test_algo (algo)) return gpg_error (GPG_ERR_DIGEST_ALGO); if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) { log_error ("no object identifier for algo %d\n", algo); return gpg_error (GPG_ERR_INTERNAL); } frame = xtrymalloc (asnlen + digestlen); if (!frame) return out_of_core (); memcpy (frame, asn, asnlen); memcpy (frame+asnlen, digest, digestlen); if (DBG_CRYPTO) log_printhex ("encoded hash:", frame, asnlen+digestlen); *r_val = frame; *r_len = asnlen+digestlen; return 0; }
static int rsa_pkcs1_encode_sig(gcry_mpi_t *r_result, size_t size, const uint8_t *hash, int algo) { uint8_t asn[100]; uint8_t frame[4096/8]; size_t asnlen = sizeof(asn); size_t hashlen = gcry_md_get_algo_dlen(algo); if (gcry_md_algo_info(algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) return VLC_EGENERIC; if (!hashlen || hashlen + asnlen + 4 > size) return VLC_EGENERIC; frame[0] = 0; frame[1] = 1; /* block type */ int pad = size - hashlen - asnlen - 3 ; memset (&frame[2], 0xff, pad ); frame[2+pad] = 0; memcpy(&frame[3+pad], asn, asnlen); memcpy(&frame[3+pad+asnlen], hash, hashlen); if (gcry_mpi_scan(r_result, GCRYMPI_FMT_USG, frame, size, &size)) return VLC_EGENERIC; return VLC_SUCCESS; }
static void run_selftest (int algo) { gpg_error_t err; size_t n; n = 1; err = gcry_md_algo_info (algo, GCRYCTL_SELFTEST, NULL, &n); if (err && gpg_err_code (err) != GPG_ERR_NOT_IMPLEMENTED) fail ("extended selftest for %s (%d) failed: %s", gcry_md_algo_name (algo), algo, gpg_strerror (err)); else if (err && verbose) show ("extended selftest for %s (%d) not implemented", gcry_md_algo_name (algo), algo); else if (verbose) show ("extended selftest for %s (%d) passed", gcry_md_algo_name (algo), algo); }
static int do_encode_md (gcry_md_hd_t md, int algo, int pkalgo, unsigned int nbits, gcry_sexp_t pkey, gcry_mpi_t *r_val) { int n; size_t nframe; unsigned char *frame; if (pkalgo == GCRY_PK_DSA || pkalgo == GCRY_PK_ECDSA) { unsigned int qbits; if ( pkalgo == GCRY_PK_ECDSA ) qbits = gcry_pk_get_nbits (pkey); else qbits = get_dsa_qbits (pkey); if ( (qbits%8) ) { log_error(_("DSA requires the hash length to be a" " multiple of 8 bits\n")); return gpg_error (GPG_ERR_INTERNAL); } /* Don't allow any Q smaller than 160 bits. We don't want someone to issue signatures from a key with a 16-bit Q or something like that, which would look correct but allow trivial forgeries. Yes, I know this rules out using MD5 with DSA. ;) */ if (qbits < 160) { log_error (_("%s key uses an unsafe (%u bit) hash\n"), gcry_pk_algo_name (pkalgo), qbits); return gpg_error (GPG_ERR_INTERNAL); } /* Check if we're too short. Too long is safe as we'll automatically left-truncate. */ nframe = gcry_md_get_algo_dlen (algo); if (nframe < qbits/8) { log_error (_("a %u bit hash is not valid for a %u bit %s key\n"), (unsigned int)nframe*8, gcry_pk_get_nbits (pkey), gcry_pk_algo_name (pkalgo)); /* FIXME: we need to check the requirements for ECDSA. */ if (nframe < 20 || pkalgo == GCRY_PK_DSA ) return gpg_error (GPG_ERR_INTERNAL); } frame = xtrymalloc (nframe); if (!frame) return out_of_core (); memcpy (frame, gcry_md_read (md, algo), nframe); n = nframe; /* Truncate. */ if (n > qbits/8) n = qbits/8; } else { int i; unsigned char asn[100]; size_t asnlen; size_t len; nframe = (nbits+7) / 8; asnlen = DIM(asn); if (!algo || gcry_md_test_algo (algo)) return gpg_error (GPG_ERR_DIGEST_ALGO); if (gcry_md_algo_info (algo, GCRYCTL_GET_ASNOID, asn, &asnlen)) { log_error ("no object identifier for algo %d\n", algo); return gpg_error (GPG_ERR_INTERNAL); } len = gcry_md_get_algo_dlen (algo); if ( len + asnlen + 4 > nframe ) { log_error ("can't encode a %d bit MD into a %d bits frame\n", (int)(len*8), (int)nbits); return gpg_error (GPG_ERR_INTERNAL); } /* We encode the MD in this way: * * 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes) * * PAD consists of FF bytes. */ frame = xtrymalloc (nframe); if (!frame) return out_of_core (); n = 0; frame[n++] = 0; frame[n++] = 1; /* block type */ i = nframe - len - asnlen -3 ; assert ( i > 1 ); memset ( frame+n, 0xff, i ); n += i; frame[n++] = 0; memcpy ( frame+n, asn, asnlen ); n += asnlen; memcpy ( frame+n, gcry_md_read(md, algo), len ); n += len; assert ( n == nframe ); } if (DBG_CRYPTO) { int j; log_debug ("encoded hash:"); for (j=0; j < nframe; j++) log_printf (" %02X", frame[j]); log_printf ("\n"); } gcry_mpi_scan (r_val, GCRYMPI_FMT_USG, frame, n, &nframe); xfree (frame); return 0; }