f6639b758f6dac14888c54e2cb7607bb73cdb9ca
[users/jgh/exim.git] / src / util / src / ed25519_privkey_pem_to_pubkey_raw_b64.c
1
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5
6 #include <stdarg.h>
7 #include <stddef.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 /* Unix includes */
14
15 typedef unsigned char uschar;
16
17 #define CS   (char *)
18 #define US   (unsigned char *)
19
20 #define FALSE         0
21 #define TRUE          1
22
23
24
25 #ifdef HAVE_GNUTLS
26
27
28 #include <gnutls/gnutls.h>
29 #include <gnutls/abstract.h>
30 #include <gnutls/x509.h>
31
32 #if GNUTLS_VERSION_NUMBER >= 0x030600
33 # define SIGN_HAVE_ED25519
34 #endif
35
36
37
38 static uschar *enc64table =
39   US"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
40
41 uschar *
42 b64encode(uschar *clear, int len)
43 {
44 uschar *code = malloc(4*((len+2)/3) + 2);
45 uschar *p = code;
46
47 while (len-- >0)
48   {
49   int x, y;
50
51   x = *clear++;
52   *p++ = enc64table[(x >> 2) & 63];
53
54   if (len-- <= 0)
55     {
56     *p++ = enc64table[(x << 4) & 63];
57     *p++ = '=';
58     *p++ = '=';
59     break;
60     }
61
62   y = *clear++;
63   *p++ = enc64table[((x << 4) | ((y >> 4) & 15)) & 63];
64
65   if (len-- <= 0)
66     {
67     *p++ = enc64table[(y << 2) & 63];
68     *p++ = '=';
69     break;
70     }
71
72   x = *clear++;
73   *p++ = enc64table[((y << 2) | ((x >> 6) & 3)) & 63];
74
75   *p++ = enc64table[x & 63];
76   }
77
78 *p = 0;
79
80 return code;
81 }
82
83 /*************************************************
84 *                 Main Program                   *
85 *************************************************/
86
87
88 int
89 main(int argc, char **argv)
90 {
91 uschar * pemfile = argv[1];
92 int fd;
93 uschar buf[1024];
94 int len, rc;
95 gnutls_privkey_t privkey;
96 gnutls_datum_t k;
97 gnutls_pubkey_t pubkey;
98 uschar * b64;
99
100 #ifdef SIGN_HAVE_ED25519
101 if ((fd = open(CS pemfile, O_RDONLY)) < 0)
102   exit(1);
103
104 if ((len = read(fd, buf, sizeof(buf)-1)) < 0)
105   exit(2);
106
107 k.data = buf;
108 k.size = len;
109
110 if (  (rc = gnutls_privkey_init(&privkey))
111    || (rc = gnutls_privkey_import_x509_raw(privkey, &k, GNUTLS_X509_FMT_PEM, NULL, GNUTLS_PKCS_PLAIN))
112    || (rc = gnutls_pubkey_init(&pubkey))
113    || (rc = gnutls_pubkey_import_privkey(pubkey, privkey, GNUTLS_KEY_DIGITAL_SIGNATURE, 0))
114    || (rc = gnutls_pubkey_export_ecc_raw2(pubkey, NULL, &k, NULL, GNUTLS_EXPORT_FLAG_NO_LZ))
115    )
116   fprintf(stderr, "%s\n", gnutls_strerror(rc));
117
118 b64 = b64encode(k.data, k.size);
119
120 printf("%s\n", b64);
121 exit(0);
122
123 #else
124 fprintf(stderr, "No support for ed25519 signing in GnuTLS (version %s)\n", gnutls_check_version(NULL));
125 exit(3);
126 #endif
127 }
128
129 #endif
130
131 #ifdef HAVE_OPENSSL
132 int
133 main(int argc, char **argv)
134 {
135 fprintf(stderr, "No support for ed25519 signing in OpenSSL\n");
136 exit(3);
137 }
138
139 #endif