void hash_bench (char **argv, int argc) { int i, algo; bench_print_section ("hash", "Hash"); bench_print_header (14, ""); if (argv && argc) { for (i = 0; i < argc; i++) { algo = gcry_md_map_name (argv[i]); if (algo) _hash_bench (algo); } } else { for (i = 1; i < 400; i++) if (!gcry_md_test_algo (i)) _hash_bench (i); } bench_print_footer (14); }
int crypt_hash_init(struct crypt_hash **ctx, const char *name) { struct crypt_hash *h; unsigned int flags = 0; assert(crypto_backend_initialised); h = malloc(sizeof(*h)); if (!h) return -ENOMEM; h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags)); if (!h->hash_id) { free(h); return -EINVAL; } if (gcry_md_open(&h->hd, h->hash_id, flags)) { free(h); return -EINVAL; } h->hash_len = gcry_md_get_algo_dlen(h->hash_id); *ctx = h; return 0; }
int crypt_hmac_init(struct crypt_hmac **ctx, const char *name, const void *buffer, size_t length) { struct crypt_hmac *h; unsigned int flags = GCRY_MD_FLAG_HMAC; assert(crypto_backend_initialised); h = malloc(sizeof(*h)); if (!h) return -ENOMEM; h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags)); if (!h->hash_id) { free(h); return -EINVAL; } if (gcry_md_open(&h->hd, h->hash_id, flags)) { free(h); return -EINVAL; } if (gcry_md_setkey(h->hd, buffer, length)) { gcry_md_close(h->hd); free(h); return -EINVAL; } h->hash_len = gcry_md_get_algo_dlen(h->hash_id); *ctx = h; return 0; }
/* PBKDF */ int crypt_pbkdf(const char *kdf, const char *hash, const char *password, size_t password_length, const char *salt, size_t salt_length, char *key, size_t key_length, unsigned int iterations) { const char *hash_name = crypt_hash_compat_name(hash, NULL); #if USE_INTERNAL_PBKDF2 if (!kdf || strncmp(kdf, "pbkdf2", 6)) return -EINVAL; return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length, iterations, key_length, key, 0); #else /* USE_INTERNAL_PBKDF2 */ int hash_id = gcry_md_map_name(hash_name); int kdf_id; if (!hash_id) return -EINVAL; if (kdf && !strncmp(kdf, "pbkdf2", 6)) kdf_id = GCRY_KDF_PBKDF2; else return -EINVAL; if (gcry_kdf_derive(password, password_length, kdf_id, hash_id, salt, salt_length, iterations, key_length, key)) return -EINVAL; return 0; #endif /* USE_INTERNAL_PBKDF2 */ }
int crypt_hash_size(const char *name) { const int hash_id = gcry_md_map_name(name); if (!hash_id) return -EINVAL; return gcry_md_get_algo_dlen(hash_id); }
static crypto_t _hash_new(crypto_t c, const gchar *algoname) { c->algo = gcry_md_map_name(algoname); if (c->algo ==0) { return (_fail(c, g_strdup_printf("algorithm `%s' was not available", algoname))); } return (c); }
/* HASH */ int crypt_hash_size(const char *name) { int hash_id; assert(crypto_backend_initialised); hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL)); if (!hash_id) return -EINVAL; return gcry_md_get_algo_dlen(hash_id); }
int my_hash(const char alg[], const unsigned char input[], const unsigned int input_len, unsigned char output[]) { int md = gcry_md_map_name(alg); unsigned int mdlen = gcry_md_get_algo_dlen(md); gchar *keybuf = g_new0(gchar, mdlen); memset(keybuf, 0, mdlen); gcry_md_hash_buffer(md, keybuf, input, input_len); //copy size_t i = 0; for(i = 0; i<mdlen; ++i) { output[i] = keybuf[ i%mdlen ]; } return 0; }
int P_hash(const char *digest, unsigned char *dest, int dlen, unsigned char *secret, int sslen, unsigned char *seed, int slen) { unsigned char hmac[48]; uint32_t hlen; gcry_md_hd_t md; uint32_t tmpslen; unsigned char tmpseed[slen]; unsigned char *out = dest; int pending = dlen; int algo = gcry_md_map_name(digest); int algolen = gcry_md_get_algo_dlen(algo); // Copy initial seed memcpy(tmpseed, seed, slen); tmpslen = slen; // Calculate enough data to fill destination while (pending > 0) { gcry_md_open(&md, algo, GCRY_MD_FLAG_HMAC); gcry_md_setkey(md, secret, sslen); gcry_md_write(md, tmpseed, tmpslen); memcpy(tmpseed, gcry_md_read(md, algo), algolen); tmpslen = algolen; gcry_md_close(md); gcry_md_open(&md, algo, GCRY_MD_FLAG_HMAC); gcry_md_setkey(md, secret, sslen); gcry_md_write(md, tmpseed, tmpslen); gcry_md_write(md, seed, slen); memcpy(hmac, gcry_md_read(md, algo), algolen); hlen = algolen; hlen = (hlen > pending) ? pending : hlen; memcpy(out, hmac, hlen); out += hlen; pending -= hlen; } return hlen; }
/* Return the hash algorithm from a KSBA sig-val. SIGVAL is a canonical encoded S-expression. Return 0 if the hash algorithm is not encoded in SIG-VAL or it is not supported by libgcrypt. */ int hash_algo_from_sigval (const unsigned char *sigval) { const unsigned char *s = sigval; size_t n; int depth; char buffer[50]; if (!s || *s != '(') return 0; /* Invalid S-expression. */ s++; n = snext (&s); if (!n) return 0; /* Invalid S-expression. */ if (!smatch (&s, n, "sig-val")) return 0; /* Not a sig-val. */ if (*s != '(') return 0; /* Invalid S-expression. */ s++; /* Skip over the algo+parameter list. */ depth = 1; if (sskip (&s, &depth) || depth) return 0; /* Invalid S-expression. */ if (*s != '(') return 0; /* No futher list. */ /* Check whether this is (hash ALGO). */ s++; n = snext (&s); if (!n) return 0; /* Invalid S-expression. */ if (!smatch (&s, n, "hash")) return 0; /* Not a "hash" keyword. */ n = snext (&s); if (!n || n+1 >= sizeof (buffer)) return 0; /* Algorithm string is missing or too long. */ memcpy (buffer, s, n); buffer[n] = 0; return gcry_md_map_name (buffer); }
int crypt_hmac_init(crypt_hmac **ctx, const char *name, bool isHmac) { unsigned int flags = isHmac ? GCRY_MD_FLAG_HMAC : 0; crypt_hmac *h = reinterpret_cast<crypt_hmac*>(malloc(sizeof(*h))); if (!h) return -ENOMEM; h->hash_id = gcry_md_map_name(name); if (!h->hash_id) { free(h); return -EINVAL; } if (gcry_md_open(&h->hd, h->hash_id, flags)) { free(h); return -EINVAL; } h->hash_len = gcry_md_get_algo_dlen(h->hash_id); *ctx = h; return 0; }
/* Check the signature on CERT using the ISSUER_CERT. This function does only test the cryptographic signature and nothing else. It is assumed that the ISSUER_CERT is valid. */ static gpg_error_t check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { gpg_error_t err; const char *algoid; gcry_md_hd_t md; int i, algo; ksba_sexp_t p; size_t n; gcry_sexp_t s_sig, s_hash, s_pkey; const char *s; char algo_name[16+1]; /* hash algorithm name converted to lower case. */ int digestlen; unsigned char *digest; /* Hash the target certificate using the algorithm from that certificate. */ algoid = ksba_cert_get_digest_algo (cert); algo = gcry_md_map_name (algoid); if (!algo) { log_error (_("unknown hash algorithm '%s'\n"), algoid? algoid:"?"); return gpg_error (GPG_ERR_GENERAL); } s = gcry_md_algo_name (algo); for (i=0; *s && i < sizeof algo_name - 1; s++, i++) algo_name[i] = tolower (*s); algo_name[i] = 0; err = gcry_md_open (&md, algo, 0); if (err) { log_error ("md_open failed: %s\n", gpg_strerror (err)); return err; } if (DBG_HASHING) gcry_md_debug (md, "hash.cert"); err = ksba_cert_hash (cert, 1, HASH_FNC, md); if (err) { log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (err)); gcry_md_close (md); return err; } gcry_md_final (md); /* Get the signature value out of the target certificate. */ p = ksba_cert_get_sig_val (cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); return gpg_error (GPG_ERR_BUG); } if (DBG_CRYPTO) { int j; log_debug ("signature value:"); for (j=0; j < n; j++) log_printf (" %02X", p[j]); log_printf ("\n"); } err = gcry_sexp_sscan ( &s_sig, NULL, p, n); ksba_free (p); if (err) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err)); gcry_md_close (md); return err; } /* Get the public key from the issuer certificate. */ p = ksba_cert_get_public_key (issuer_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } err = gcry_sexp_sscan ( &s_pkey, NULL, p, n); ksba_free (p); if (err) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (err)); gcry_md_close (md); gcry_sexp_release (s_sig); return err; } /* Prepare the values for signature verification. At this point we have these values: S_PKEY - S-expression with the issuer's public key. S_SIG - Signature value as given in the certrificate. MD - Finalized hash context with hash of the certificate. ALGO_NAME - Lowercase hash algorithm name */ digestlen = gcry_md_get_algo_dlen (algo); digest = gcry_md_read (md, algo); if (pk_algo_from_sexp (s_pkey) == GCRY_PK_DSA) { if (digestlen != 20) { log_error (_("DSA requires the use of a 160 bit hash algorithm\n")); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_pkey); return gpg_error (GPG_ERR_INTERNAL); } if ( gcry_sexp_build (&s_hash, NULL, "(data(flags raw)(value %b))", (int)digestlen, digest) ) BUG (); } else /* Not DSA. */ { if ( gcry_sexp_build (&s_hash, NULL, "(data(flags pkcs1)(hash %s %b))", algo_name, (int)digestlen, digest) ) BUG (); } err = gcry_pk_verify (s_sig, s_hash, s_pkey); if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (err)); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return err; }
static int pkcs5_pbkdf2(const char *hash, const char *P, size_t Plen, const char *S, size_t Slen, unsigned int c, unsigned int dkLen, char *DK, int perfcheck) { gcry_md_hd_t prf; char U[MAX_PRF_BLOCK_LEN]; char T[MAX_PRF_BLOCK_LEN]; int PRF, i, k, rc = -EINVAL; unsigned int u, hLen, l, r; unsigned char *p; size_t tmplen = Slen + 4; char *tmp; tmp = alloca(tmplen); if (tmp == NULL) return -ENOMEM; if (init_crypto()) return -ENOSYS; PRF = gcry_md_map_name(hash); if (PRF == 0) return -EINVAL; hLen = gcry_md_get_algo_dlen(PRF); if (hLen == 0 || hLen > MAX_PRF_BLOCK_LEN) return -EINVAL; if (c == 0) return -EINVAL; if (dkLen == 0) return -EINVAL; /* * * Steps: * * 1. If dkLen > (2^32 - 1) * hLen, output "derived key too long" and * stop. */ if (dkLen > 4294967295U) return -EINVAL; /* * 2. Let l be the number of hLen-octet blocks in the derived key, * rounding up, and let r be the number of octets in the last * block: * * l = CEIL (dkLen / hLen) , * r = dkLen - (l - 1) * hLen . * * Here, CEIL (x) is the "ceiling" function, i.e. the smallest * integer greater than, or equal to, x. */ l = dkLen / hLen; if (dkLen % hLen) l++; r = dkLen - (l - 1) * hLen; /* * 3. For each block of the derived key apply the function F defined * below to the password P, the salt S, the iteration count c, and * the block index to compute the block: * * T_1 = F (P, S, c, 1) , * T_2 = F (P, S, c, 2) , * ... * T_l = F (P, S, c, l) , * * where the function F is defined as the exclusive-or sum of the * first c iterates of the underlying pseudorandom function PRF * applied to the password P and the concatenation of the salt S * and the block index i: * * F (P, S, c, i) = U_1 \xor U_2 \xor ... \xor U_c * * where * * U_1 = PRF (P, S || INT (i)) , * U_2 = PRF (P, U_1) , * ... * U_c = PRF (P, U_{c-1}) . * * Here, INT (i) is a four-octet encoding of the integer i, most * significant octet first. * * 4. Concatenate the blocks and extract the first dkLen octets to * produce a derived key DK: * * DK = T_1 || T_2 || ... || T_l<0..r-1> * * 5. Output the derived key DK. * * Note. The construction of the function F follows a "belt-and- * suspenders" approach. The iterates U_i are computed recursively to * remove a degree of parallelism from an opponent; they are exclusive- * ored together to reduce concerns about the recursion degenerating * into a small set of values. * */ if(gcry_md_open(&prf, PRF, GCRY_MD_FLAG_HMAC)) return -EINVAL; if (gcry_md_setkey(prf, P, Plen)) goto out; for (i = 1; (uint) i <= l; i++) { memset(T, 0, hLen); for (u = 1; u <= c ; u++) { gcry_md_reset(prf); if (u == 1) { memcpy(tmp, S, Slen); tmp[Slen + 0] = (i & 0xff000000) >> 24; tmp[Slen + 1] = (i & 0x00ff0000) >> 16; tmp[Slen + 2] = (i & 0x0000ff00) >> 8; tmp[Slen + 3] = (i & 0x000000ff) >> 0; gcry_md_write(prf, tmp, tmplen); } else { gcry_md_write(prf, U, hLen); } p = gcry_md_read(prf, PRF); if (p == NULL) goto out; memcpy(U, p, hLen); for (k = 0; (uint) k < hLen; k++) T[k] ^= U[k]; if (perfcheck && __PBKDF2_performance) { rc = 0; goto out; } if (perfcheck) __PBKDF2_global_j++; }
int main(int argc, char *argv[]) { static struct option long_options[] = { { "block-size", required_argument, 0, 'b' }, { "hash-algo", required_argument, 0, 'h' }, { "hash-algorithm", required_argument, 0, 'h' }, { "max-iter", required_argument, 0, 'i' }, { "freeze", required_argument, 0, 'f' }, { "loop", no_argument, 0, 'l' }, { 0, 0, 0, 0 }, }; int i; int freeze_count = 0; gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); if (!gcry_check_version(GCRYPT_VERSION)) { fprintf(stderr, "libgcrypt version mismatch\n"); return 1; } while (1) { int c; c = getopt_long(argc, argv, "b:h:i:f:l", long_options, NULL); if (c == -1) break; switch (c) { case 'b': if (sscanf(optarg, "%i", &block_size) != 1) { fprintf(stderr, "cannot parse block size: " "%s\n", optarg); return 1; } if ((block_size & 7) != 0) { fprintf(stderr, "error: block size must be " "a multiple of 8\n"); return 1; } break; case 'h': hash_algo = gcry_md_map_name(optarg); if (hash_algo == 0) { fprintf(stderr, "unknown hash algorithm " "name: %s\n", optarg); return 1; } break; case 'i': if (sscanf(optarg, "%i", &max_iterations) != 1) { fprintf(stderr, "cannot parse iteration " "count: %s\n", optarg); return 1; } break; case 'f': if (freeze_count == MAX_FREEZE) { fprintf(stderr, "too many --freeze options\n"); return 1; } freeze_fs[freeze_count++] = optarg; break; case 'l': loop = 1; break; case '?': return 1; default: abort(); } } if (optind + 4 != argc) { fprintf(stderr, "%s: [opts] <src> <srchashmap> <dst> " "<dsthashmap>\n", argv[0]); fprintf(stderr, " -b, --block-size=SIZE hash block size\n"); fprintf(stderr, " -f, --freeze=MOUNTPOINT freeze " "filesystem\n"); fprintf(stderr, " -h, --hash-algo=ALGO hash algorithm\n"); fprintf(stderr, " -i, --max-iter=ITER maximum number of " "iterations\n"); fprintf(stderr, " -l, --loop create consistent " "image copy\n"); return 1; } hash_size = gcry_md_get_algo_dlen(hash_algo); fd_src = open(argv[optind], O_RDONLY); if (fd_src < 0) { perror("opening src"); return 1; } sizeblocks = lseek(fd_src, 0, SEEK_END); if (sizeblocks < 0) { perror("lseek"); return 1; } sizeblocks = (sizeblocks + block_size - 1) / block_size; if (strcmp(argv[optind + 1], "-")) { int fd_srchashmap; if (loop) { fprintf(stderr, "consistent image copy requested, " "but source hashmap specified\n"); return 1; } fd_srchashmap = open(argv[optind + 1], O_RDONLY); if (fd_srchashmap < 0) { perror("opening srchashmap"); return 1; } srchashmap = malloc(sizeblocks * hash_size); if (srchashmap == NULL) { fprintf(stderr, "out of memory allocating hash map\n"); return 1; } if (read(fd_srchashmap, srchashmap, sizeblocks * hash_size) != sizeblocks * hash_size) { fprintf(stderr, "error reading hash map\n"); return 1; } close(fd_srchashmap); } else { srchashmap = NULL; } fd_dst = open(argv[optind + 2], O_CREAT | O_RDWR, 0666); if (fd_dst < 0) { perror("opening dst"); return 1; } fd_dsthashmap = open(argv[optind + 3], O_CREAT | O_RDWR, 0666); if (fd_dsthashmap < 0) { perror("opening dsthashmap"); return 1; } dsthashmap = malloc(sizeblocks * hash_size); if (dsthashmap == NULL) { fprintf(stderr, "out of memory allocating hash map\n"); return 1; } if (read(fd_dsthashmap, dsthashmap, sizeblocks * hash_size) != sizeblocks * hash_size) { fprintf(stderr, "error reading hash map\n"); return 1; } setup_sig_handlers(); if (freeze_count) { for (i = 0; i < MAX_FREEZE; i++) freeze_fd[i] = -1; atexit(thaw_fs); fprintf(stderr, "freezing filesystems\n"); for (i = 0; i < freeze_count; i++) { int fd; fd = open(freeze_fs[i], O_RDONLY); if (fd < 0) { fprintf(stderr, "error opening freeze mount " "point %s (%s)\n", freeze_fs[i], strerror(errno)); return 1; } if (ioctl(fd, FIFREEZE, 0) < 0) { fprintf(stderr, "error freezing fs %s (%s)\n", freeze_fs[i], strerror(errno)); return 1; } freeze_fd[i] = fd; } } if (loop) { for (i = 0; i < max_iterations; i++) { fd_off = 0; again = 0; fprintf(stderr, "scanning for differences... "); run_threads(copy_thread_no_hashmap); if (!signal_quit_flag) { fprintf(stderr, "done " " \n"); } if (!again) break; if (i == max_iterations - 1) { fprintf(stderr, "maximum iteration count " "reached, bailing out\n"); } else { fprintf(stderr, "repeating scanning due to " "differences\n"); } } } else { fd_off = 0; if (srchashmap == NULL) { fprintf(stderr, "scanning for differences... "); run_threads(copy_thread_no_hashmap); } else { off_t off; mismatch_idx = 0; mismatch_cnt = 0; for (off = 0; off < sizeblocks; off++) { if (memcmp(srchashmap + off * hash_size, dsthashmap + off * hash_size, hash_size)) { mismatch_cnt++; } } fprintf(stderr, "copying differences... "); run_threads(copy_thread_hashmap); } if (!signal_quit_flag) { fprintf(stderr, "done " " \n"); } } fprintf(stderr, "flushing buffers... "); close(fd_src); close(fd_dst); close(fd_dsthashmap); fprintf(stderr, "done\n"); return signal_quit_flag ? EXIT_FAILURE : EXIT_SUCCESS; }
int main (int argc, char **argv) { int last_argc = -1; int gigs = 0; int algo = 0; int idx; if (argc) { argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--")) { argc--; argv++; break; } else if (!strcmp (*argv, "--help")) { fputs ("usage: " PGM " [options] [algos]\n" "Options:\n" " --verbose print timings etc.\n" " --debug flyswatter\n" " --gigs N Run a test on N GiB\n", stdout); exit (0); } else if (!strcmp (*argv, "--verbose")) { verbose++; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose += 2; debug++; argc--; argv++; } else if (!strcmp (*argv, "--gigs")) { argc--; argv++; if (argc) { gigs = atoi (*argv); argc--; argv++; } } else if (!strncmp (*argv, "--", 2)) die ("unknown option '%s'", *argv); } if (gigs < 0 || gigs > 1024*1024) die ("value for --gigs must be in the range 0 to %d", 1024*1024); gcry_control (GCRYCTL_DISABLE_SECMEM, 0); if (!gcry_check_version (GCRYPT_VERSION)) die ("version mismatch\n"); if (debug) gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); /* A quick check that all given algorithms are valid. */ for (idx=0; idx < argc; idx++) { algo = gcry_md_map_name (argv[idx]); if (!algo) fail ("invalid algorithm '%s'", argv[idx]); } if (error_count) exit (1); /* Start checking. */ start_timer (); if (!argc) { for (algo=1; algo < 400; algo++) if (!gcry_md_test_algo (algo)) { if (!gigs) run_selftest (algo); else run_longtest (algo, gigs); } } else { for (idx=0; idx < argc; idx++) { algo = gcry_md_map_name (argv[idx]); if (!algo) die ("invalid algorithm '%s'", argv[idx]); if (!gigs) run_selftest (algo); else run_longtest (algo, gigs); } } stop_timer (); if (missing_test_vectors) fail ("Some test vectors are missing"); if (verbose) show ("All tests completed in %s. Errors: %d\n", elapsed_time (), error_count); return !!error_count; }
int check_hash(int fd_no, const char *f_md5, const char *f_sha256){ int md5algo, sha256algo, i; char hashed_md5[33], hashed_sha256[65]; struct stat fileStat; char *buffer; const char *md5name = gcry_md_algo_name(GCRY_MD_MD5); const char *sha256name = gcry_md_algo_name(GCRY_MD_SHA256); md5algo = gcry_md_map_name(md5name); sha256algo = gcry_md_map_name(sha256name); off_t fsize = 0, donesize = 0, diff = 0; if(fstat(fd_no, &fileStat) < 0){ perror("Fstat error"); return -1; } fsize = fileStat.st_size; FILE *fp = fdopen(fd_no, "r"); if(fp == NULL){ printf("Cannot open file for read\n"); return -1; } gcry_md_hd_t hd_md5; gcry_md_hd_t hd_sha256; gcry_md_open(&hd_md5, md5algo, 0); gcry_md_open(&hd_sha256, sha256algo, 0); if(fsize < 10024){ buffer = malloc(fsize); if(buffer == NULL){ printf("malloc error\n"); return -1; } fread(buffer, 1, fsize, fp); gcry_md_write(hd_md5, buffer, fsize); gcry_md_write(hd_sha256, buffer, fsize); goto nowhile; } buffer = malloc(10024); if(buffer == NULL){ printf("malloc error\n"); return -1; } while(fsize > donesize){ fread(buffer, 1, 10024, fp); gcry_md_write(hd_md5, buffer, 10024); gcry_md_write(hd_sha256, buffer, 10024); donesize+=10024; diff=fsize-donesize; if(diff < 10024){ fread(buffer, 1, diff, fp); gcry_md_write(hd_md5, buffer, diff); gcry_md_write(hd_sha256, buffer, diff); break; } } nowhile: gcry_md_final(hd_md5); gcry_md_final(hd_sha256); unsigned const char *md5 = gcry_md_read(hd_md5, md5algo); unsigned const char *sha256 = gcry_md_read(hd_sha256, sha256algo); for(i=0; i<16; i++){ sprintf(hashed_md5+(i*2), "%02x", md5[i]); } for(i=0; i<32; i++){ sprintf(hashed_sha256+(i*2), "%02x", sha256[i]); } hashed_md5[32] = '\0'; hashed_sha256[64] = '\0'; free(buffer); fclose(fp); close(fd_no); if((strcmp(f_md5, hashed_md5) != 0) || (strcmp(f_sha256, hashed_sha256) != 0)){ printf("Error: checksum mismatch\n"); } else printf("Checksum ok\n"); gcry_md_close(hd_md5); gcry_md_close(hd_sha256); return 0; }
static void md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; int i, j, repcount; char buf_base[1000+15]; size_t bufsize = 1000; char *buf; char *largebuf_base; char *largebuf; char digest[512/8]; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if (in_fips_mode && i == GCRY_MD_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; } buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); algo = gcry_md_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); exit (1); } err = gcry_md_open (&hd, algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); exit (1); } for (i=0; i < bufsize; i++) buf[i] = i; printf ("%-12s", gcry_md_algo_name (algo)); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) gcry_md_write (hd, buf, bufsize); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 10000; i++) gcry_md_write (hd, buf, bufsize/10); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_reset (hd); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000000; i++) gcry_md_write (hd, buf, 1); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 1000; i++) for (j=0; j < bufsize; j++) gcry_md_putc (hd, buf[j]); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); fflush (stdout); gcry_md_close (hd); /* Now 100 hash operations on 10000 bytes using the fast function. We initialize the buffer so that all memory pages are committed and we have repeatable values. */ if (gcry_md_get_algo_dlen (algo) > sizeof digest) die ("digest buffer too short\n"); largebuf_base = malloc (10000+15); if (!largebuf_base) die ("out of core\n"); largebuf = (largebuf_base + ((16 - ((size_t)largebuf_base & 0x0f)) % buffer_alignment)); for (i=0; i < 10000; i++) largebuf[i] = i; start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) for (i=0; i < 100; i++) gcry_md_hash_buffer (algo, digest, largebuf, 10000); stop_timer (); printf (" %s", elapsed_time ()); free (largebuf_base); putchar ('\n'); fflush (stdout); }
gboolean egg_hkdf_perform (const gchar *hash_algo, gconstpointer input, gsize n_input, gconstpointer salt, gsize n_salt, gconstpointer info, gsize n_info, gpointer output, gsize n_output) { gpointer alloc = NULL; gpointer buffer = NULL; gcry_md_hd_t md1, md2; guint hash_len; gint i; gint flags, algo; gsize step, n_buffer; guchar *at; gcry_error_t gcry; algo = gcry_md_map_name (hash_algo); g_return_val_if_fail (algo != 0, FALSE); hash_len = gcry_md_get_algo_dlen (algo); g_return_val_if_fail (hash_len != 0, FALSE); g_return_val_if_fail (n_output <= 255 * hash_len, FALSE); /* Buffer we need to for intermediate stuff */ if (gcry_is_secure (input)) { flags = GCRY_MD_FLAG_SECURE; buffer = gcry_malloc_secure (hash_len); } else { flags = 0; buffer = gcry_malloc (hash_len); } g_return_val_if_fail (buffer, FALSE); n_buffer = 0; /* Salt defaults to hash_len zeros */ if (!salt) { salt = alloc = g_malloc0 (hash_len); n_salt = hash_len; } /* Step 1: Extract */ gcry = gcry_md_open (&md1, algo, GCRY_MD_FLAG_HMAC | flags); g_return_val_if_fail (gcry == 0, FALSE); gcry = gcry_md_setkey (md1, salt, n_salt); g_return_val_if_fail (gcry == 0, FALSE); gcry_md_write (md1, input, n_input); /* Step 2: Expand */ gcry = gcry_md_open (&md2, algo, GCRY_MD_FLAG_HMAC | flags); g_return_val_if_fail (gcry == 0, FALSE); gcry = gcry_md_setkey (md2, gcry_md_read (md1, algo), hash_len); g_return_val_if_fail (gcry == 0, FALSE); gcry_md_close (md1); at = output; for (i = 1; i < 256; ++i) { gcry_md_reset (md2); gcry_md_write (md2, buffer, n_buffer); gcry_md_write (md2, info, n_info); gcry_md_putc (md2, i); n_buffer = hash_len; memcpy (buffer, gcry_md_read (md2, algo), n_buffer); step = MIN (n_buffer, n_output); memcpy (at, buffer, step); n_output -= step; at += step; if (!n_output) break; } g_free (alloc); gcry_free (buffer); return TRUE; }
/* Check the signature on CERT using the ISSUER-CERT. This function does only test the cryptographic signature and nothing else. It is assumed that the ISSUER_CERT is valid. */ int gpgsm_check_cert_sig (ksba_cert_t issuer_cert, ksba_cert_t cert) { const char *algoid; gcry_md_hd_t md; int rc, algo; gcry_mpi_t frame; ksba_sexp_t p; size_t n; gcry_sexp_t s_sig, s_hash, s_pkey; algo = gcry_md_map_name ( (algoid=ksba_cert_get_digest_algo (cert))); if (!algo) { log_error ("unknown hash algorithm '%s'\n", algoid? algoid:"?"); if (algoid && ( !strcmp (algoid, "1.2.840.113549.1.1.2") ||!strcmp (algoid, "1.2.840.113549.2.2"))) log_info (_("(this is the MD2 algorithm)\n")); return gpg_error (GPG_ERR_GENERAL); } rc = gcry_md_open (&md, algo, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); return rc; } if (DBG_HASHING) gcry_md_debug (md, "hash.cert"); rc = ksba_cert_hash (cert, 1, HASH_FNC, md); if (rc) { log_error ("ksba_cert_hash failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); return rc; } gcry_md_final (md); p = ksba_cert_get_sig_val (cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); return gpg_error (GPG_ERR_BUG); } if (DBG_CRYPTO) { int j; log_debug ("signature value:"); for (j=0; j < n; j++) log_printf (" %02X", p[j]); log_printf ("\n"); } rc = gcry_sexp_sscan ( &s_sig, NULL, (char*)p, n); ksba_free (p); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); return rc; } p = ksba_cert_get_public_key (issuer_cert); n = gcry_sexp_canon_len (p, 0, NULL, NULL); if (!n) { log_error ("libksba did not return a proper S-Exp\n"); gcry_md_close (md); ksba_free (p); gcry_sexp_release (s_sig); return gpg_error (GPG_ERR_BUG); } rc = gcry_sexp_sscan ( &s_pkey, NULL, (char*)p, n); ksba_free (p); if (rc) { log_error ("gcry_sexp_scan failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); gcry_sexp_release (s_sig); return rc; } rc = do_encode_md (md, algo, pk_algo_from_sexp (s_pkey), gcry_pk_get_nbits (s_pkey), s_pkey, &frame); if (rc) { gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_pkey); return rc; } /* put hash into the S-Exp s_hash */ if ( gcry_sexp_build (&s_hash, NULL, "%m", frame) ) BUG (); gcry_mpi_release (frame); rc = gcry_pk_verify (s_sig, s_hash, s_pkey); if (DBG_X509) log_debug ("gcry_pk_verify: %s\n", gpg_strerror (rc)); gcry_md_close (md); gcry_sexp_release (s_sig); gcry_sexp_release (s_hash); gcry_sexp_release (s_pkey); return rc; }
static void md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; int i; char buf[1000]; gcry_error_t err = GPG_ERR_NO_ERROR; if (!algoname) { for (i=1; i < 400; i++) if ( !gcry_md_test_algo (i) ) md_bench (gcry_md_algo_name (i)); return; } algo = gcry_md_map_name (algoname); if (!algo) { fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); exit (1); } err = gcry_md_open (&hd, algo, 0); if (err) { fprintf (stderr, PGM ": error opening hash algorithm `%s'\n", algoname); exit (1); } for (i=0; i < sizeof buf; i++) buf[i] = i; printf ("%-12s", gcry_md_algo_name (algo)); start_timer (); for (i=0; i < 1000; i++) gcry_md_write (hd, buf, sizeof buf); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_reset (hd); start_timer (); for (i=0; i < 10000; i++) gcry_md_write (hd, buf, sizeof buf/10); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_reset (hd); start_timer (); for (i=0; i < 1000000; i++) gcry_md_write (hd, "", 1); gcry_md_final (hd); stop_timer (); printf (" %s", elapsed_time ()); gcry_md_close (hd); putchar ('\n'); }
/* Perform a verify operation. To verify detached signatures, data_fd must be different than -1. With OUT_FP given and a non-detached signature, the signed material is written to that stream. */ int gpgsm_verify (ctrl_t ctrl, int in_fd, int data_fd, FILE *out_fp) { int i, rc; Base64Context b64reader = NULL; Base64Context b64writer = NULL; ksba_reader_t reader; ksba_writer_t writer = NULL; ksba_cms_t cms = NULL; ksba_stop_reason_t stopreason; ksba_cert_t cert; KEYDB_HANDLE kh; gcry_md_hd_t data_md = NULL; int signer; const char *algoid; int algo; int is_detached; FILE *fp = NULL; char *p; audit_set_type (ctrl->audit, AUDIT_TYPE_VERIFY); kh = keydb_new (0); if (!kh) { log_error (_("failed to allocated keyDB handle\n")); rc = gpg_error (GPG_ERR_GENERAL); goto leave; } fp = fdopen ( dup (in_fd), "rb"); if (!fp) { rc = gpg_error (gpg_err_code_from_errno (errno)); log_error ("fdopen() failed: %s\n", strerror (errno)); goto leave; } rc = gpgsm_create_reader (&b64reader, ctrl, fp, 0, &reader); if (rc) { log_error ("can't create reader: %s\n", gpg_strerror (rc)); goto leave; } if (out_fp) { rc = gpgsm_create_writer (&b64writer, ctrl, out_fp, NULL, &writer); if (rc) { log_error ("can't create writer: %s\n", gpg_strerror (rc)); goto leave; } } rc = ksba_cms_new (&cms); if (rc) goto leave; rc = ksba_cms_set_reader_writer (cms, reader, writer); if (rc) { log_error ("ksba_cms_set_reader_writer failed: %s\n", gpg_strerror (rc)); goto leave; } rc = gcry_md_open (&data_md, 0, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); goto leave; } if (DBG_HASHING) gcry_md_start_debug (data_md, "vrfy.data"); audit_log (ctrl->audit, AUDIT_SETUP_READY); is_detached = 0; do { rc = ksba_cms_parse (cms, &stopreason); if (rc) { log_error ("ksba_cms_parse failed: %s\n", gpg_strerror (rc)); goto leave; } if (stopreason == KSBA_SR_NEED_HASH) { is_detached = 1; audit_log (ctrl->audit, AUDIT_DETACHED_SIGNATURE); if (opt.verbose) log_info ("detached signature\n"); } if (stopreason == KSBA_SR_NEED_HASH || stopreason == KSBA_SR_BEGIN_DATA) { audit_log (ctrl->audit, AUDIT_GOT_DATA); /* We are now able to enable the hash algorithms */ for (i=0; (algoid=ksba_cms_get_digest_algo_list (cms, i)); i++) { algo = gcry_md_map_name (algoid); if (!algo) { log_error ("unknown hash algorithm `%s'\n", algoid? algoid:"?"); if (algoid && ( !strcmp (algoid, "1.2.840.113549.1.1.2") ||!strcmp (algoid, "1.2.840.113549.2.2"))) log_info (_("(this is the MD2 algorithm)\n")); audit_log_s (ctrl->audit, AUDIT_BAD_DATA_HASH_ALGO, algoid); } else { if (DBG_X509) log_debug ("enabling hash algorithm %d (%s)\n", algo, algoid? algoid:""); gcry_md_enable (data_md, algo); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo); } } if (opt.extra_digest_algo) { if (DBG_X509) log_debug ("enabling extra hash algorithm %d\n", opt.extra_digest_algo); gcry_md_enable (data_md, opt.extra_digest_algo); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, opt.extra_digest_algo); } if (is_detached) { if (data_fd == -1) { log_info ("detached signature w/o data " "- assuming certs-only\n"); audit_log (ctrl->audit, AUDIT_CERT_ONLY_SIG); } else audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, hash_data (data_fd, data_md)); } else { ksba_cms_set_hash_function (cms, HASH_FNC, data_md); } } else if (stopreason == KSBA_SR_END_DATA) { /* The data bas been hashed */ audit_log_ok (ctrl->audit, AUDIT_DATA_HASHING, 0); } } while (stopreason != KSBA_SR_READY); if (b64writer) { rc = gpgsm_finish_writer (b64writer); if (rc) { log_error ("write failed: %s\n", gpg_strerror (rc)); audit_log_ok (ctrl->audit, AUDIT_WRITE_ERROR, rc); goto leave; } } if (data_fd != -1 && !is_detached) { log_error ("data given for a non-detached signature\n"); rc = gpg_error (GPG_ERR_CONFLICT); audit_log (ctrl->audit, AUDIT_USAGE_ERROR); goto leave; } for (i=0; (cert=ksba_cms_get_cert (cms, i)); i++) { /* Fixme: it might be better to check the validity of the certificate first before entering it into the DB. This way we would avoid cluttering the DB with invalid certificates. */ audit_log_cert (ctrl->audit, AUDIT_SAVE_CERT, cert, keydb_store_cert (cert, 0, NULL)); ksba_cert_release (cert); } cert = NULL; for (signer=0; ; signer++) { char *issuer = NULL; ksba_sexp_t sigval = NULL; ksba_isotime_t sigtime, keyexptime; ksba_sexp_t serial; char *msgdigest = NULL; size_t msgdigestlen; char *ctattr; int sigval_hash_algo; int info_pkalgo; unsigned int verifyflags; rc = ksba_cms_get_issuer_serial (cms, signer, &issuer, &serial); if (!signer && gpg_err_code (rc) == GPG_ERR_NO_DATA && data_fd == -1 && is_detached) { log_info ("certs-only message accepted\n"); rc = 0; break; } if (rc) { if (signer && rc == -1) rc = 0; break; } gpgsm_status (ctrl, STATUS_NEWSIG, NULL); audit_log_i (ctrl->audit, AUDIT_NEW_SIG, signer); if (DBG_X509) { log_debug ("signer %d - issuer: `%s'\n", signer, issuer? issuer:"[NONE]"); log_debug ("signer %d - serial: ", signer); gpgsm_dump_serial (serial); log_printf ("\n"); } if (ctrl->audit) { char *tmpstr = gpgsm_format_sn_issuer (serial, issuer); audit_log_s (ctrl->audit, AUDIT_SIG_NAME, tmpstr); xfree (tmpstr); } rc = ksba_cms_get_signing_time (cms, signer, sigtime); if (gpg_err_code (rc) == GPG_ERR_NO_DATA) *sigtime = 0; else if (rc) { log_error ("error getting signing time: %s\n", gpg_strerror (rc)); *sigtime = 0; /* (we can't encode an error in the time string.) */ } rc = ksba_cms_get_message_digest (cms, signer, &msgdigest, &msgdigestlen); if (!rc) { size_t is_enabled; algoid = ksba_cms_get_digest_algo (cms, signer); algo = gcry_md_map_name (algoid); if (DBG_X509) log_debug ("signer %d - digest algo: %d\n", signer, algo); is_enabled = sizeof algo; if ( gcry_md_info (data_md, GCRYCTL_IS_ALGO_ENABLED, &algo, &is_enabled) || !is_enabled) { log_error ("digest algo %d (%s) has not been enabled\n", algo, algoid?algoid:""); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "unsupported"); goto next_signer; } } else if (gpg_err_code (rc) == GPG_ERR_NO_DATA) { assert (!msgdigest); rc = 0; algoid = NULL; algo = 0; } else /* real error */ { audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); break; } rc = ksba_cms_get_sigattr_oids (cms, signer, "1.2.840.113549.1.9.3", &ctattr); if (!rc) { const char *s; if (DBG_X509) log_debug ("signer %d - content-type attribute: %s", signer, ctattr); s = ksba_cms_get_content_oid (cms, 1); if (!s || strcmp (ctattr, s)) { log_error ("content-type attribute does not match " "actual content-type\n"); ksba_free (ctattr); ctattr = NULL; audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } ksba_free (ctattr); ctattr = NULL; } else if (rc != -1) { log_error ("error getting content-type attribute: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } rc = 0; sigval = ksba_cms_get_sig_val (cms, signer); if (!sigval) { log_error ("no signature value available\n"); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } sigval_hash_algo = hash_algo_from_sigval (sigval); if (DBG_X509) { log_debug ("signer %d - signature available (sigval hash=%d)", signer, sigval_hash_algo); /* log_printhex ("sigval ", sigval, */ /* gcry_sexp_canon_len (sigval, 0, NULL, NULL)); */ } if (!sigval_hash_algo) sigval_hash_algo = algo; /* Fallback used e.g. with old libksba. */ /* Find the certificate of the signer */ keydb_search_reset (kh); rc = keydb_search_issuer_sn (kh, issuer, serial); if (rc) { if (rc == -1) { log_error ("certificate not found\n"); rc = gpg_error (GPG_ERR_NO_PUBKEY); } else log_error ("failed to find the certificate: %s\n", gpg_strerror(rc)); { char numbuf[50]; sprintf (numbuf, "%d", rc); gpgsm_status2 (ctrl, STATUS_ERROR, "verify.findkey", numbuf, NULL); } audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "no-cert"); goto next_signer; } rc = keydb_get_cert (kh, &cert); if (rc) { log_error ("failed to get cert: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } log_info (_("Signature made ")); if (*sigtime) dump_isotime (sigtime); else log_printf (_("[date not given]")); log_printf (_(" using certificate ID 0x%08lX\n"), gpgsm_get_short_fingerprint (cert, NULL)); audit_log_i (ctrl->audit, AUDIT_DATA_HASH_ALGO, algo); if (msgdigest) { /* Signed attributes are available. */ gcry_md_hd_t md; unsigned char *s; /* Check that the message digest in the signed attributes matches the one we calculated on the data. */ s = gcry_md_read (data_md, algo); if ( !s || !msgdigestlen || gcry_md_get_algo_dlen (algo) != msgdigestlen || !s || memcmp (s, msgdigest, msgdigestlen) ) { char *fpr; log_error (_("invalid signature: message digest attribute " "does not match computed one\n")); if (DBG_X509) { if (msgdigest) log_printhex ("message: ", msgdigest, msgdigestlen); if (s) log_printhex ("computed: ", s, gcry_md_get_algo_dlen (algo)); } fpr = gpgsm_fpr_and_name_for_status (cert); gpgsm_status (ctrl, STATUS_BADSIG, fpr); xfree (fpr); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } audit_log_i (ctrl->audit, AUDIT_ATTR_HASH_ALGO, sigval_hash_algo); rc = gcry_md_open (&md, sigval_hash_algo, 0); if (rc) { log_error ("md_open failed: %s\n", gpg_strerror (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } if (DBG_HASHING) gcry_md_start_debug (md, "vrfy.attr"); ksba_cms_set_hash_function (cms, HASH_FNC, md); rc = ksba_cms_hash_signed_attrs (cms, signer); if (rc) { log_error ("hashing signed attrs failed: %s\n", gpg_strerror (rc)); gcry_md_close (md); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "error"); goto next_signer; } rc = gpgsm_check_cms_signature (cert, sigval, md, sigval_hash_algo, &info_pkalgo); gcry_md_close (md); } else { rc = gpgsm_check_cms_signature (cert, sigval, data_md, algo, &info_pkalgo); } if (rc) { char *fpr; log_error ("invalid signature: %s\n", gpg_strerror (rc)); fpr = gpgsm_fpr_and_name_for_status (cert); gpgsm_status (ctrl, STATUS_BADSIG, fpr); xfree (fpr); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } rc = gpgsm_cert_use_verify_p (cert); /*(this displays an info message)*/ if (rc) { gpgsm_status_with_err_code (ctrl, STATUS_ERROR, "verify.keyusage", gpg_err_code (rc)); rc = 0; } if (DBG_X509) log_debug ("signature okay - checking certs\n"); audit_log (ctrl->audit, AUDIT_VALIDATE_CHAIN); rc = gpgsm_validate_chain (ctrl, cert, *sigtime? sigtime : "19700101T000000", keyexptime, 0, NULL, 0, &verifyflags); { char *fpr, *buf, *tstr; fpr = gpgsm_fpr_and_name_for_status (cert); if (gpg_err_code (rc) == GPG_ERR_CERT_EXPIRED) { gpgsm_status (ctrl, STATUS_EXPKEYSIG, fpr); rc = 0; } else gpgsm_status (ctrl, STATUS_GOODSIG, fpr); xfree (fpr); fpr = gpgsm_get_fingerprint_hexstring (cert, GCRY_MD_SHA1); tstr = strtimestamp_r (sigtime); buf = xasprintf ("%s %s %s %s 0 0 %d %d 00", fpr, tstr, *sigtime? sigtime : "0", *keyexptime? keyexptime : "0", info_pkalgo, algo); xfree (tstr); xfree (fpr); gpgsm_status (ctrl, STATUS_VALIDSIG, buf); xfree (buf); } audit_log_ok (ctrl->audit, AUDIT_CHAIN_STATUS, rc); if (rc) /* of validate_chain */ { log_error ("invalid certification chain: %s\n", gpg_strerror (rc)); if (gpg_err_code (rc) == GPG_ERR_BAD_CERT_CHAIN || gpg_err_code (rc) == GPG_ERR_BAD_CERT || gpg_err_code (rc) == GPG_ERR_BAD_CA_CERT || gpg_err_code (rc) == GPG_ERR_CERT_REVOKED) gpgsm_status_with_err_code (ctrl, STATUS_TRUST_NEVER, NULL, gpg_err_code (rc)); else gpgsm_status_with_err_code (ctrl, STATUS_TRUST_UNDEFINED, NULL, gpg_err_code (rc)); audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "bad"); goto next_signer; } audit_log_s (ctrl->audit, AUDIT_SIG_STATUS, "good"); for (i=0; (p = ksba_cert_get_subject (cert, i)); i++) { log_info (!i? _("Good signature from") : _(" aka")); log_printf (" \""); gpgsm_print_name (log_get_stream (), p); log_printf ("\"\n"); ksba_free (p); } /* Print a note if this is a qualified signature. */ { size_t qualbuflen; char qualbuffer[1]; rc = ksba_cert_get_user_data (cert, "is_qualified", &qualbuffer, sizeof (qualbuffer), &qualbuflen); if (!rc && qualbuflen) { if (*qualbuffer) { log_info (_("This is a qualified signature\n")); if (!opt.qualsig_approval) log_info (_("Note, that this software is not officially approved " "to create or verify such signatures.\n")); } } else if (gpg_err_code (rc) != GPG_ERR_NOT_FOUND) log_error ("get_user_data(is_qualified) failed: %s\n", gpg_strerror (rc)); } gpgsm_status (ctrl, STATUS_TRUST_FULLY, (verifyflags & VALIDATE_FLAG_CHAIN_MODEL)? "0 chain": "0 shell"); next_signer: rc = 0; xfree (issuer); xfree (serial); xfree (sigval); xfree (msgdigest); ksba_cert_release (cert); cert = NULL; } rc = 0; leave: ksba_cms_release (cms); gpgsm_destroy_reader (b64reader); gpgsm_destroy_writer (b64writer); keydb_release (kh); gcry_md_close (data_md); if (fp) fclose (fp); if (rc) { char numbuf[50]; sprintf (numbuf, "%d", rc ); gpgsm_status2 (ctrl, STATUS_ERROR, "verify.leave", numbuf, NULL); } return rc; }