/** Convert X.509 RSA public key into gcrypt internal sexp form. Only RSA public keys are accepted at the moment. The resul is stored in *sexp, which must be freed (using ) when not needed anymore. *sexp must be NULL on entry, since it is overwritten. */ gpg_err_code_t keyutil_get_cert_sexp ( unsigned char *der, size_t len, gcry_sexp_t *p_sexp ) { gpg_err_code_t error = GPG_ERR_GENERAL; gcry_mpi_t n_mpi = NULL; gcry_mpi_t e_mpi = NULL; gcry_sexp_t sexp = NULL; if ( (error = keyutil_get_cert_mpi ( der, len, &n_mpi, &e_mpi )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( gcry_sexp_build ( &sexp, NULL, "(public-key (rsa (n %m) (e %m)))", n_mpi, e_mpi ) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } *p_sexp = sexp; sexp = NULL; error = GPG_ERR_NO_ERROR; cleanup: if (n_mpi != NULL) { gcry_mpi_release (n_mpi); n_mpi = NULL; } if (e_mpi != NULL) { gcry_mpi_release (e_mpi); e_mpi = NULL; } if (sexp != NULL) { gcry_sexp_release (sexp); sexp = NULL; } return error; }
gpg_error_t cmd_genkey (assuan_context_t ctx, char *line) { gpg_err_code_t error = GPG_ERR_GENERAL; pkcs11h_certificate_id_t cert_id = NULL; gcry_mpi_t n_mpi = NULL; gcry_mpi_t e_mpi = NULL; unsigned char *n_hex = NULL; unsigned char *e_hex = NULL; char *n_resp = strdup ("n "); char *e_resp = strdup ("e "); unsigned char *blob = NULL; char *serial = NULL; char *key = NULL; size_t blob_size; char timestamp[100] = {0}; while (*line != '\x0' && !isdigit (*line)) { if (*line == '-') { static const char *ts = "--timestamp="; char *p = line; while (*line != '\x0' && !isspace (*line)) { line++; } line++; if (!strncmp (p, ts, strlen (ts))) { p += strlen (ts); sprintf (timestamp, "%d", (int)isotime2epoch (p)); } } else { line++; } } if (*line == '\x0') { error = GPG_ERR_INV_DATA; goto cleanup; } if (strlen (timestamp) == 0) { sprintf (timestamp, "%d", (int)time (NULL)); } if ( (error = _get_certificate_by_name ( ctx, NULL, atoi(line), &cert_id, &key )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = assuan_write_status ( ctx, "KEY-FPR", key )) != GPG_ERR_NO_ERROR || (error = assuan_write_status( ctx, "KEY-CREATED-AT", timestamp )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ((error = get_serial_of_tokenid(cert_id->token_id, &serial)) != GPG_ERR_NO_ERROR) { goto cleanup; } if ( (error = assuan_write_status ( ctx, "SERIALNO", serial )) != GPG_ERR_NO_ERROR || (error = get_cert_blob ( ctx, cert_id, &blob, &blob_size )) != GPG_ERR_NO_ERROR || (error = keyutil_get_cert_mpi ( blob, blob_size, &n_mpi, &e_mpi )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( gcry_mpi_aprint ( GCRYMPI_FMT_HEX, &n_hex, NULL, n_mpi ) || gcry_mpi_aprint ( GCRYMPI_FMT_HEX, &e_hex, NULL, e_mpi ) ) { error = GPG_ERR_BAD_KEY; goto cleanup; } if ( !encoding_strappend (&n_resp, (char *)n_hex) || !encoding_strappend (&e_resp, (char *)e_hex) ) { error = GPG_ERR_ENOMEM; goto cleanup; } if ( (error = assuan_write_status( ctx, "KEY-DATA", n_resp )) != GPG_ERR_NO_ERROR ) { goto cleanup; } if ( (error = assuan_write_status( ctx, "KEY-DATA", e_resp )) != GPG_ERR_NO_ERROR ) { goto cleanup; } error = GPG_ERR_NO_ERROR; cleanup: if (n_mpi != NULL) { gcry_mpi_release (n_mpi); n_mpi = NULL; } if (e_mpi != NULL) { gcry_mpi_release (e_mpi); e_mpi = NULL; } if (n_hex != NULL) { gcry_free (n_hex); n_hex = NULL; } if (e_hex != NULL) { gcry_free (e_hex); e_hex = NULL; } if (n_resp != NULL) { free (n_resp); n_resp = NULL; } if (e_resp != NULL) { free (e_resp); e_resp = NULL; } if (blob != NULL) { free (blob); blob = NULL; } if (cert_id != NULL) { pkcs11h_certificate_freeCertificateId (cert_id); cert_id = NULL; } if (serial != NULL) { free(serial); serial = NULL; } return gpg_error (error); }