- #include "gnutls-helpers.h"
- #include <gnutls/openpgp.h>
- #include <gnutls/x509.h>
- /* for waitpid() */
- #include <sys/types.h>
- #include <sys/wait.h>
- /* for time() */
- #include <time.h>
- /* for htons() */
- #include <arpa/inet.h>
- /*
- Author: Daniel Kahn Gillmor <dkg@fifthhorseman.net>
- Date: Sun, 2008-04-20
- License: GPL v3 or later
- monkeysphere public key translator: execute this with an ssh
- private key on stdin. It currently only works with RSA keys.
- it should eventually work with OpenSSH-style public keys instead of
- the full private key, but it was easier to do this way.
- It shoud spit out a version of the public key suitable for acting
- as an OpenPGP public sub key packet.
- */
- int main(int argc, char* argv[]) {
- gnutls_datum_t data;
- int ret;
- gnutls_x509_privkey_t x509_privkey;
- gnutls_openpgp_crt_t openpgp_crt;
- gnutls_openpgp_keyid_t keyid;
- printable_keyid p_keyid;
- unsigned int keyidx;
- unsigned int usage, bits;
- gnutls_pk_algorithm_t algo;
- unsigned char packettag;
- unsigned char openpgpversion;
- time_t timestamp;
- uint32_t clunkytime;
- unsigned char openpgpalgo;
- unsigned int packetlen;
- uint16_t plen;
- gnutls_datum_t m, e, d, p, q, u, g, y;
- gnutls_datum_t algolabel;
- char output_data[10240];
- char userid[10240];
- size_t uidsz = sizeof(userid);
- const gnutls_datum_t* all[5];
- int pipefd;
- pid_t child_pid;
- char* const args[] = {"/usr/bin/base64", "--wrap=0", NULL};
- const char* algoname;
- int mpicount;
- int pipestatus;
- init_gnutls();
-
- init_datum(&data);
- init_datum(&m);
- init_datum(&e);
- init_datum(&d);
- init_datum(&p);
- init_datum(&q);
- init_datum(&u);
- init_datum(&g);
- init_datum(&y);
- init_datum(&algolabel);
- init_keyid(keyid);
- /* slurp in the private key from stdin */
- if (ret = set_datum_fd(&data, 0), ret) {
- err("didn't read file descriptor 0\n");
- return 1;
- }
- if (ret = gnutls_x509_privkey_init(&x509_privkey), ret) {
- err("Failed to initialize private key structure (error: %d)\n", ret);
- return 1;
- }
- err("assuming PEM formatted private key\n");
- if (ret = gnutls_x509_privkey_import(x509_privkey, &data, GNUTLS_X509_FMT_PEM), ret) {
- err("failed to import the PEM-encoded private key (error: %d)\n", ret);
- return ret;
- }
- algo = gnutls_x509_privkey_get_pk_algorithm(x509_privkey);
- if (algo < 0) {
- err("failed to get the algorithm of the PEM-encoded public key (error: %d)\n", algo);
- return algo;
- } else if (algo == GNUTLS_PK_RSA) {
- err("RSA private key\n");
- ret = gnutls_x509_privkey_export_rsa_raw(x509_privkey, &m, &e, &d, &p, &q, &u);
- if (GNUTLS_E_SUCCESS != ret) {
- err ("failed to export RSA key parameters (error: %d)\n", ret);
- return 1;
- }
- err("Modulus size %d, exponent size %d\n", m.size, e.size);
- } else if (algo == GNUTLS_PK_DSA) {
- err("DSA Key, not implemented!!\n", bits);
- return 1;
- } else {
- err("Key was not RSA or DSA -- can't deal! (actual algorithm was: %d)\n", algo);
- return 1;
- }
- /* now we have algo, and the various MPI data are set. Can we
- export them as a public subkey packet? */
- /* this packet should be tagged 14, and should contain:
- 1 octet: version (4)
- 4 octets: time of generation (seconds since 1970)
- 1 octet: algo (http://tools.ietf.org/html/rfc4880#section-5.5.2 implies 1 for RSA)
-
- MPI: modulus
- MPI: exponent
- */
- packetlen = 1 + 4 + 1;
- /* FIXME: this is RSA only. for DSA, there'll be more: */
- packetlen += get_openpgp_mpi_size(&m) + get_openpgp_mpi_size(&e);
- /* FIXME: we should generate this bound more cleanly -- i just
- happen to know that 65535 is 2^16-1: */
- if (packetlen > 65535) {
- err("packet length is too long (%d)\n", packetlen);
- return 1;
- }
- /* we're going to emit an old-style packet, with tag 14 (public
- subkey), with a two-octet packet length */
- packettag = 0x80 | (14 << 2) | 1;
-
- write(1, &packettag, sizeof(packettag));
- plen = htons(packetlen);
- write(1, &plen, sizeof(plen));
- openpgpversion = 4;
- write(1, &openpgpversion, 1);
- timestamp = time(NULL);
- clunkytime = htonl(timestamp);
- write(1, &clunkytime, 4);
- /* FIXME: handle things other than RSA */
- openpgpalgo = 1;
- write(1, &openpgpalgo, 1);
-
- write_openpgp_mpi_to_fd(1, &m);
- write_openpgp_mpi_to_fd(1, &e);
- gnutls_x509_privkey_deinit(x509_privkey);
- gnutls_global_deinit();
- return 0;
- }
|