static int test_sign(const char *private_key, const char *public_key, bool success) { char *sig = NULL; char *file = NULL; int ret = -1; sig = str_or_die("%s/sig", test_dir); file = __FILE__; if (sign(private_key, public_key, file, sig) < 0) { goto error; } if (!signature_init(public_key, NULL)) { goto error; } // Check if signature match check_goto(signature_verify(file, sig, false) == success, error); // Check signature against wrong file check_goto(signature_verify(sig, sig, false) == false, error); ret = 0; error: signature_deinit(); free(sig); return ret; }
/*Run a benchmark with different curve parameters and print CSV result to out *Comma-Separated Values (CSV), RFC 4180: http://tools.ietf.org/html/rfc4180 */ void benchmark(FILE* out, int i) { //Print CSV header fprintf(out, "Curve, Public key generation time, Signature generation time, Signature verification time, Operation time\r\n"); //If the illiterator is invalid use default illiterator if(i < 1) i = DEFAULT_TEST_ILLITERATOR; //Loop through all curves, since we're benchmarking them towards eachother. int curve_i; for(curve_i = 0;curve_i < NUMBER_OF_CURVES;curve_i++) { //Set initial timer clock_t start = clock(); int test_i; //Load curve domain_parameters curve = domain_parameters_init(); domain_parameters_load_curve(curve, curve_i); //Print curve name fprintf(out, "%s, ", curve->name); //Get a private key mpz_t d;mpz_init(d); mpz_sub_ui(d, curve->n, 2); //Private key must be between 1 and n-1 //Get a message to sign mpz_t m;mpz_init(m); mpz_sub_ui(m, curve->n, 2); //Must be between 1 and n-1 //NOTE: I assume we're using a hash algorithm giving result with the biggest bit-length possible //Initialize a signature signature sig = signature_init(); //Initialize public key point Q = point_init(); //Save time at the start of public key generation clock_t start_gen_Q = clock(); //Generate public key for(test_i = 0; test_i < i; test_i++) signature_generate_key(Q, d, curve); //Save time between public key generation and signature generation clock_t start_sign = clock(); //Generate signature for(test_i = 0; test_i < i; test_i++) signature_sign(sig, m, d, curve); //Save time between signature generation and signature verification clock_t start_verify = clock(); //Verify signature bool result; for(test_i = 0; test_i < i; test_i++) result = signature_verify(m, sig, Q, curve); //Save time after verification clock_t end_verify = clock(); //Clear variables mpz_clear(d); domain_parameters_clear(curve); signature_clear(sig); mpz_clear(m); //Save time before printing clock_t end = clock(); //Print public key generation time fprintf(out, "%.4f, ", ((double) (start_sign - start_gen_Q)) / CLOCKS_PER_SEC); //Print signature generation time fprintf(out, "%.4f, ", ((double) (start_verify - start_sign)) / CLOCKS_PER_SEC); //Print signature verification time fprintf(out, "%.4f, ", ((double) (end_verify - start_verify)) / CLOCKS_PER_SEC); //Print operation time if(result) fprintf(out, "%.4f", ((double) (end - start)) / CLOCKS_PER_SEC); else fprintf(out, "-1"); //print a new line fprintf(out, "\r\n"); //Acoording to RFC4180 this must be done with CLRF } }
retvalue signature_requirement_add(struct signature_requirement **list_p, const char *condition) { struct signature_requirement *req; const char *full_condition = condition; retvalue r; r = signature_init(false); if (RET_WAS_ERROR(r)) return r; if (condition == NULL || strcmp(condition, "blindtrust") == 0) return RET_NOTHING; /* no need to add the same condition multiple times */ for (req = *list_p ; req != NULL ; req = req->next) { if (strcmp(req->condition, condition) == 0) return RET_NOTHING; } req = malloc(sizeof_requirement(1)); if (FAILEDTOALLOC(req)) return RET_ERROR_OOM; req->next = NULL; req->condition = strdup(condition); if (FAILEDTOALLOC(req->condition)) { free(req); return RET_ERROR_OOM; } req->num_keys = 0; do { bool allow_subkeys, allow_bad; char *next_key IFSTUPIDCC(=NULL); r = parse_condition_part(&allow_subkeys, &allow_bad, full_condition, &condition, &next_key); ASSERT_NOT_NOTHING(r); if (RET_WAS_ERROR(r)) { signature_requirements_free(req); return r; } req->keys[req->num_keys].allow_bad = allow_bad; r = load_key(next_key, allow_subkeys, allow_bad, full_condition, &req->keys[req->num_keys].key, &req->keys[req->num_keys].subkey); free(next_key); if (RET_WAS_ERROR(r)) { signature_requirements_free(req); return r; } req->num_keys++; if (*condition != '\0') { struct signature_requirement *h; h = realloc(req, sizeof_requirement(req->num_keys+1)); if (FAILEDTOALLOC(h)) { signature_requirements_free(req); return r; } req = h; } else break; } while (true); req->next = *list_p; *list_p = req; return RET_OK; }
static retvalue extract_signed_data(const char *buffer, size_t bufferlen, const char *filenametoshow, char **chunkread, /*@null@*/ /*@out@*/struct signatures **signatures_p, bool *brokensignature) { char *chunk; gpg_error_t err; gpgme_data_t dh, dh_gpg; size_t plain_len; char *plain_data; retvalue r; struct signatures *signatures = NULL; bool foundbroken = false; r = signature_init(false); if (RET_WAS_ERROR(r)) return r; err = gpgme_data_new_from_mem(&dh_gpg, buffer, bufferlen, 0); if (err != 0) return gpgerror(err); err = gpgme_data_new(&dh); if (err != 0) { gpgme_data_release(dh_gpg); return gpgerror(err); } err = gpgme_op_verify(context, dh_gpg, NULL, dh); if (gpg_err_code(err) == GPG_ERR_NO_DATA) { if (verbose > 5) fprintf(stderr, "Data seems not to be signed trying to use directly....\n"); gpgme_data_release(dh); gpgme_data_release(dh_gpg); return RET_NOTHING; } else { if (err != 0) { gpgme_data_release(dh_gpg); gpgme_data_release(dh); return gpgerror(err); } if (signatures_p != NULL || brokensignature != NULL) { r = checksigs(filenametoshow, (signatures_p!=NULL)?&signatures:NULL, (brokensignature!=NULL)?&foundbroken:NULL); if (RET_WAS_ERROR(r)) { gpgme_data_release(dh_gpg); gpgme_data_release(dh); return r; } } gpgme_data_release(dh_gpg); plain_data = gpgme_data_release_and_get_mem(dh, &plain_len); if (plain_data == NULL) { fprintf(stderr, "(not yet fatal) ERROR: libgpgme failed to extract the plain data out of\n" "'%s'.\n" "While it did so in a way indicating running out of memory, experience says\n" "this also happens when gpg returns a error code it does not understand.\n" "To check this please try running gpg --verify '%s' manually.\n" "Continuing extracting it ignoring all signatures...", filenametoshow, filenametoshow); signatures_free(signatures); return RET_NOTHING; } if (signatures != NULL) { r = check_primary_keys(signatures); if (RET_WAS_ERROR(r)) { signatures_free(signatures); return r; } } } if (FAILEDTOALLOC(plain_data)) r = RET_ERROR_OOM; else { size_t len; const char *afterchanges; chunk = malloc(plain_len + 1); len = chunk_extract(chunk, plain_data, plain_len, false, &afterchanges); if (len == 0) { fprintf(stderr, "Could only find spaces within '%s'!\n", filenametoshow); free(chunk); r = RET_ERROR; } else if (afterchanges != plain_data + plain_len) { if (*afterchanges == '\0') fprintf(stderr, "Unexpected \\0 character within '%s'!\n", filenametoshow); else fprintf(stderr, "Unexpected data after ending empty line in '%s'!\n", filenametoshow); free(chunk); r = RET_ERROR; } else *chunkread = chunk; } #ifdef HAVE_GPGPME_FREE gpgme_free(plain_data); #else free(plain_data); #endif if (RET_IS_OK(r)) { if (signatures_p != NULL) *signatures_p = signatures; if (brokensignature != NULL) *brokensignature = foundbroken; } else { signatures_free(signatures); } return r; }