static void back_and_forth_one (int testno, const char *buffer, size_t length) { gcry_error_t rc; gcry_sexp_t se, se1; size_t n, n1; char *p1; rc = gcry_sexp_new (&se, buffer, length, 1); if (rc) { fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc)); return; } n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0); if (!n1) { fail ("baf %d: get required length for canon failed\n", testno); return; } p1 = gcry_xmalloc (n1); n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1); if (n1 != n+1) /* sprints adds an extra 0 but dies not return it */ { fail ("baf %d: length mismatch for canon\n", testno); return; } rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free); if (rc) { fail ("baf %d: gcry_sexp_create failed: %s\n", testno, gpg_strerror (rc)); return; } gcry_sexp_release (se1); /* Again but with memory checking. */ p1 = gcry_xmalloc (n1+2); *p1 = '\x55'; p1[n1+1] = '\xaa'; n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1); if (n1 != n+1) /* sprints adds an extra 0 but does not return it */ { fail ("baf %d: length mismatch for canon\n", testno); return; } if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (1)\n", testno); rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL); if (rc) { fail ("baf %d: gcry_sexp_create failed: %s\n", testno, gpg_strerror (rc)); return; } if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (2)\n", testno); gcry_sexp_release (se1); if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (3)\n", testno); gcry_free (p1); /* FIXME: we need a lot more tests */ gcry_sexp_release (se); }
/* Same as gcry_sexp_create but don't transfer ownership */ gcry_error_t gcry_sexp_new (gcry_sexp_t *retsexp, const void *buffer, size_t length, int autodetect) { return gcry_sexp_create (retsexp, (void *)buffer, length, autodetect, NULL); }
static void back_and_forth_one (int testno, const char *buffer, size_t length) { gcry_error_t rc; gcry_sexp_t se, se1; unsigned char *canon; size_t canonlen; /* Including the hidden nul suffix. */ size_t n, n1; char *p1; rc = gcry_sexp_new (&se, buffer, length, 1); if (rc) { fail ("baf %d: gcry_sexp_new failed: %s\n", testno, gpg_strerror (rc)); return; } n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, NULL, 0); if (!n1) { fail ("baf %d: get required length for canon failed\n", testno); return; } p1 = gcry_xmalloc (n1); n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1, n1); if (n1 != n+1) /* sprints adds an extra 0 but does not return it. */ { fail ("baf %d: length mismatch for canon\n", testno); return; } canonlen = n1; canon = gcry_malloc (canonlen); memcpy (canon, p1, canonlen); rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free); if (rc) { fail ("baf %d: gcry_sexp_create failed: %s\n", testno, gpg_strerror (rc)); return; } gcry_sexp_release (se1); /* Again but with memory checking. */ p1 = gcry_xmalloc (n1+2); *p1 = '\x55'; p1[n1+1] = '\xaa'; n = gcry_sexp_sprint (se, GCRYSEXP_FMT_CANON, p1+1, n1); if (n1 != n+1) /* sprints adds an extra 0 but does not return it */ { fail ("baf %d: length mismatch for canon\n", testno); return; } if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (1)\n", testno); rc = gcry_sexp_create (&se1, p1+1, n, 0, NULL); if (rc) { fail ("baf %d: gcry_sexp_create failed: %s\n", testno, gpg_strerror (rc)); return; } if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (2)\n", testno); gcry_sexp_release (se1); if (*p1 != '\x55' || p1[n1+1] != '\xaa') fail ("baf %d: memory corrupted (3)\n", testno); gcry_free (p1); /* Check converting to advanced format. */ n1 = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, NULL, 0); if (!n1) { fail ("baf %d: get required length for advanced failed\n", testno); return; } p1 = gcry_xmalloc (n1); n = gcry_sexp_sprint (se, GCRYSEXP_FMT_ADVANCED, p1, n1); if (n1 != n+1) /* sprints adds an extra 0 but does not return it */ { fail ("baf %d: length mismatch for advanced\n", testno); return; } rc = gcry_sexp_create (&se1, p1, n, 0, gcry_free); if (rc) { fail ("baf %d: gcry_sexp_create failed: %s\n", testno, gpg_strerror (rc)); return; } if (compare_to_canon (se1, canon, canonlen)) { fail ("baf %d: converting to advanced failed: %s\n", testno, gpg_strerror (rc)); return; } gcry_sexp_release (se1); /* FIXME: we need a lot more tests */ gcry_sexp_release (se); xfree (canon); }
static gpg_error_t export_p12 (ctrl_t ctrl, const unsigned char *certimg, size_t certimglen, const char *prompt, const char *keygrip, void **r_result, size_t *r_resultlen) { gpg_error_t err = 0; void *kek = NULL; size_t keklen; unsigned char *wrappedkey = NULL; size_t wrappedkeylen; gcry_cipher_hd_t cipherhd = NULL; gcry_sexp_t s_skey = NULL; gcry_mpi_t *kparms = NULL; unsigned char *key = NULL; size_t keylen; char *passphrase = NULL; unsigned char *result = NULL; size_t resultlen; int i; *r_result = NULL; /* Get the current KEK. */ err = gpgsm_agent_keywrap_key (ctrl, 1, &kek, &keklen); if (err) { log_error ("error getting the KEK: %s\n", gpg_strerror (err)); goto leave; } /* Receive the wrapped key from the agent. */ err = gpgsm_agent_export_key (ctrl, keygrip, prompt, &wrappedkey, &wrappedkeylen); if (err) goto leave; /* Unwrap the key. */ err = gcry_cipher_open (&cipherhd, GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_AESWRAP, 0); if (err) goto leave; err = gcry_cipher_setkey (cipherhd, kek, keklen); if (err) goto leave; xfree (kek); kek = NULL; if (wrappedkeylen < 24) { err = gpg_error (GPG_ERR_INV_LENGTH); goto leave; } keylen = wrappedkeylen - 8; key = xtrymalloc_secure (keylen); if (!key) { err = gpg_error_from_syserror (); goto leave; } err = gcry_cipher_decrypt (cipherhd, key, keylen, wrappedkey, wrappedkeylen); if (err) goto leave; xfree (wrappedkey); wrappedkey = NULL; gcry_cipher_close (cipherhd); cipherhd = NULL; /* Convert to a gcrypt S-expression. */ err = gcry_sexp_create (&s_skey, key, keylen, 0, xfree_fnc); if (err) goto leave; key = NULL; /* Key is now owned by S_KEY. */ /* Get the parameters from the S-expression. */ kparms = sexp_to_kparms (s_skey); gcry_sexp_release (s_skey); s_skey = NULL; if (!kparms) { log_error ("error converting key parameters\n"); err = GPG_ERR_BAD_SECKEY; goto leave; } err = gpgsm_agent_ask_passphrase (ctrl, i18n_utf8 ("Please enter the passphrase to protect the " "new PKCS#12 object."), 1, &passphrase); if (err) goto leave; result = p12_build (kparms, certimg, certimglen, passphrase, opt.p12_charset, &resultlen); xfree (passphrase); passphrase = NULL; if (!result) err = gpg_error (GPG_ERR_GENERAL); leave: xfree (key); gcry_sexp_release (s_skey); if (kparms) { for (i=0; kparms[i]; i++) gcry_mpi_release (kparms[i]); xfree (kparms); } gcry_cipher_close (cipherhd); xfree (wrappedkey); xfree (kek); if (gpg_err_code (err) == GPG_ERR_BAD_PASSPHRASE) { /* During export this is the passphrase used to unprotect the key and not the pkcs#12 thing as in export. Therefore we can issue the regular passphrase status. FIXME: replace the all zero keyid by a regular one. */ gpgsm_status (ctrl, STATUS_BAD_PASSPHRASE, "0000000000000000"); } if (err) { xfree (result); } else { *r_result = result; *r_resultlen = resultlen; } return err; }