Line data Source code
1 : /* openpgp-oids.c - OID helper for OpenPGP
2 : * Copyright (C) 2011 Free Software Foundation, Inc.
3 : * Copyright (C) 2013 Werner Koch
4 : *
5 : * This file is part of GnuPG.
6 : *
7 : * This file is free software; you can redistribute it and/or modify
8 : * it under the terms of either
9 : *
10 : * - the GNU Lesser General Public License as published by the Free
11 : * Software Foundation; either version 3 of the License, or (at
12 : * your option) any later version.
13 : *
14 : * or
15 : *
16 : * - the GNU General Public License as published by the Free
17 : * Software Foundation; either version 2 of the License, or (at
18 : * your option) any later version.
19 : *
20 : * or both in parallel, as here.
21 : *
22 : * This file is distributed in the hope that it will be useful,
23 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 : * GNU General Public License for more details.
26 : *
27 : * You should have received a copy of the GNU General Public License
28 : * along with this program; if not, see <https://www.gnu.org/licenses/>.
29 : */
30 :
31 : #include <config.h>
32 : #include <stdlib.h>
33 : #include <errno.h>
34 : #include <ctype.h>
35 : #include <assert.h>
36 :
37 : #include "util.h"
38 : #include "openpgpdefs.h"
39 :
40 : /* A table with all our supported OpenPGP curves. */
41 : static struct {
42 : const char *name; /* Standard name. */
43 : const char *oidstr; /* IETF formatted OID. */
44 : unsigned int nbits; /* Nominal bit length of the curve. */
45 : const char *alias; /* NULL or alternative name of the curve. */
46 : int pubkey_algo; /* Required OpenPGP algo or 0 for ECDSA/ECDH. */
47 : } oidtable[] = {
48 :
49 : { "Curve25519", "1.3.6.1.4.1.3029.1.5.1", 255, "cv25519", PUBKEY_ALGO_ECDH },
50 : { "Ed25519", "1.3.6.1.4.1.11591.15.1", 255, "ed25519", PUBKEY_ALGO_EDDSA },
51 :
52 : { "NIST P-256", "1.2.840.10045.3.1.7", 256, "nistp256" },
53 : { "NIST P-384", "1.3.132.0.34", 384, "nistp384" },
54 : { "NIST P-521", "1.3.132.0.35", 521, "nistp521" },
55 :
56 : { "brainpoolP256r1", "1.3.36.3.3.2.8.1.1.7", 256 },
57 : { "brainpoolP384r1", "1.3.36.3.3.2.8.1.1.11", 384 },
58 : { "brainpoolP512r1", "1.3.36.3.3.2.8.1.1.13", 512 },
59 :
60 : { "secp256k1", "1.3.132.0.10", 256 },
61 :
62 : { NULL, NULL, 0}
63 : };
64 :
65 :
66 : /* The OID for Curve Ed25519 in OpenPGP format. */
67 : static const char oid_ed25519[] =
68 : { 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 };
69 :
70 : /* The OID for Curve25519 in OpenPGP format. */
71 : static const char oid_cv25519[] =
72 : { 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 };
73 :
74 :
75 : /* Helper for openpgp_oid_from_str. */
76 : static size_t
77 90 : make_flagged_int (unsigned long value, char *buf, size_t buflen)
78 : {
79 90 : int more = 0;
80 : int shift;
81 :
82 : /* fixme: figure out the number of bits in an ulong and start with
83 : that value as shift (after making it a multiple of 7) a more
84 : straigtforward implementation is to do it in reverse order using
85 : a temporary buffer - saves a lot of compares */
86 450 : for (more=0, shift=28; shift > 0; shift -= 7)
87 : {
88 360 : if (more || value >= (1<<shift))
89 : {
90 15 : buf[buflen++] = 0x80 | (value >> shift);
91 15 : value -= (value >> shift) << shift;
92 15 : more = 1;
93 : }
94 : }
95 90 : buf[buflen++] = value;
96 90 : return buflen;
97 : }
98 :
99 :
100 : /* Convert the OID given in dotted decimal form in STRING to an DER
101 : * encoding and store it as an opaque value at R_MPI. The format of
102 : * the DER encoded is not a regular ASN.1 object but the modified
103 : * format as used by OpenPGP for the ECC curve description. On error
104 : * the function returns and error code an NULL is stored at R_BUG.
105 : * Note that scanning STRING stops at the first white space
106 : * character. */
107 : gpg_error_t
108 21 : openpgp_oid_from_str (const char *string, gcry_mpi_t *r_mpi)
109 : {
110 : unsigned char *buf;
111 : size_t buflen;
112 : unsigned long val1, val;
113 : const char *endp;
114 : int arcno;
115 :
116 21 : *r_mpi = NULL;
117 :
118 21 : if (!string || !*string)
119 1 : return gpg_error (GPG_ERR_INV_VALUE);
120 :
121 : /* We can safely assume that the encoded OID is shorter than the string. */
122 20 : buf = xtrymalloc (1 + strlen (string) + 2);
123 20 : if (!buf)
124 0 : return gpg_error_from_syserror ();
125 : /* Save the first byte for the length. */
126 20 : buflen = 1;
127 :
128 20 : val1 = 0; /* Avoid compiler warning. */
129 20 : arcno = 0;
130 : do {
131 128 : arcno++;
132 128 : val = strtoul (string, (char**)&endp, 10);
133 128 : if (!digitp (string) || !(*endp == '.' || !*endp))
134 : {
135 1 : xfree (buf);
136 1 : return gpg_error (GPG_ERR_INV_OID_STRING);
137 : }
138 127 : if (*endp == '.')
139 108 : string = endp+1;
140 :
141 127 : if (arcno == 1)
142 : {
143 19 : if (val > 2)
144 0 : break; /* Not allowed, error catched below. */
145 19 : val1 = val;
146 : }
147 108 : else if (arcno == 2)
148 : { /* Need to combine the first two arcs in one octet. */
149 18 : if (val1 < 2)
150 : {
151 18 : if (val > 39)
152 : {
153 0 : xfree (buf);
154 0 : return gpg_error (GPG_ERR_INV_OID_STRING);
155 : }
156 18 : buf[buflen++] = val1*40 + val;
157 : }
158 : else
159 : {
160 0 : val += 80;
161 0 : buflen = make_flagged_int (val, buf, buflen);
162 : }
163 : }
164 : else
165 : {
166 90 : buflen = make_flagged_int (val, buf, buflen);
167 : }
168 127 : } while (*endp == '.');
169 :
170 19 : if (arcno == 1 || buflen < 2 || buflen > 254 )
171 : { /* It is not possible to encode only the first arc. */
172 1 : xfree (buf);
173 1 : return gpg_error (GPG_ERR_INV_OID_STRING);
174 : }
175 :
176 18 : *buf = buflen - 1;
177 18 : *r_mpi = gcry_mpi_set_opaque (NULL, buf, buflen * 8);
178 18 : if (!*r_mpi)
179 : {
180 0 : xfree (buf);
181 0 : return gpg_error_from_syserror ();
182 : }
183 18 : return 0;
184 : }
185 :
186 :
187 : /* Return a malloced string represenation of the OID in the opaque MPI
188 : A. In case of an error NULL is returned and ERRNO is set. */
189 : char *
190 461 : openpgp_oid_to_str (gcry_mpi_t a)
191 : {
192 : const unsigned char *buf;
193 : size_t length;
194 : unsigned int lengthi;
195 : char *string, *p;
196 461 : int n = 0;
197 : unsigned long val, valmask;
198 :
199 461 : valmask = (unsigned long)0xfe << (8 * (sizeof (valmask) - 1));
200 :
201 461 : if (!a
202 461 : || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)
203 461 : || !(buf = gcry_mpi_get_opaque (a, &lengthi)))
204 : {
205 0 : gpg_err_set_errno (EINVAL);
206 0 : return NULL;
207 : }
208 :
209 461 : buf = gcry_mpi_get_opaque (a, &lengthi);
210 461 : length = (lengthi+7)/8;
211 :
212 : /* The first bytes gives the length; check consistency. */
213 461 : if (!length || buf[0] != length -1)
214 : {
215 0 : gpg_err_set_errno (EINVAL);
216 0 : return NULL;
217 : }
218 : /* Skip length byte. */
219 461 : length--;
220 461 : buf++;
221 :
222 : /* To calculate the length of the string we can safely assume an
223 : upper limit of 3 decimal characters per byte. Two extra bytes
224 : account for the special first octect */
225 461 : string = p = xtrymalloc (length*(1+3)+2+1);
226 461 : if (!string)
227 0 : return NULL;
228 461 : if (!length)
229 : {
230 0 : *p = 0;
231 0 : return string;
232 : }
233 :
234 461 : if (buf[0] < 40)
235 1 : p += sprintf (p, "0.%d", buf[n]);
236 460 : else if (buf[0] < 80)
237 458 : p += sprintf (p, "1.%d", buf[n]-40);
238 : else {
239 2 : val = buf[n] & 0x7f;
240 5 : while ( (buf[n]&0x80) && ++n < length )
241 : {
242 1 : if ( (val & valmask) )
243 0 : goto badoid; /* Overflow. */
244 1 : val <<= 7;
245 1 : val |= buf[n] & 0x7f;
246 : }
247 2 : if (val < 80)
248 2 : goto badoid;
249 0 : val -= 80;
250 0 : sprintf (p, "2.%lu", val);
251 0 : p += strlen (p);
252 : }
253 2226 : for (n++; n < length; n++)
254 : {
255 1767 : val = buf[n] & 0x7f;
256 4137 : while ( (buf[n]&0x80) && ++n < length )
257 : {
258 603 : if ( (val & valmask) )
259 0 : goto badoid; /* Overflow. */
260 603 : val <<= 7;
261 603 : val |= buf[n] & 0x7f;
262 : }
263 1767 : sprintf (p, ".%lu", val);
264 1767 : p += strlen (p);
265 : }
266 :
267 459 : *p = 0;
268 459 : return string;
269 :
270 : badoid:
271 : /* Return a special OID (gnu.gnupg.badoid) to indicate the error
272 : case. The OID is broken and thus we return one which can't do
273 : any harm. Formally this does not need to be a bad OID but an OID
274 : with an arc that can't be represented in a 32 bit word is more
275 : than likely corrupt. */
276 2 : xfree (string);
277 2 : return xtrystrdup ("1.3.6.1.4.1.11591.2.12242973");
278 : }
279 :
280 :
281 :
282 : /* Return true if A represents the OID for Ed25519. */
283 : int
284 140 : openpgp_oid_is_ed25519 (gcry_mpi_t a)
285 : {
286 : const unsigned char *buf;
287 : unsigned int nbits;
288 : size_t n;
289 :
290 140 : if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
291 97 : return 0;
292 :
293 43 : buf = gcry_mpi_get_opaque (a, &nbits);
294 43 : n = (nbits+7)/8;
295 43 : return (n == DIM (oid_ed25519)
296 43 : && !memcmp (buf, oid_ed25519, DIM (oid_ed25519)));
297 : }
298 :
299 :
300 : int
301 141 : openpgp_oid_is_cv25519 (gcry_mpi_t a)
302 : {
303 : const unsigned char *buf;
304 : unsigned int nbits;
305 : size_t n;
306 :
307 141 : if (!a || !gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE))
308 0 : return 0;
309 :
310 141 : buf = gcry_mpi_get_opaque (a, &nbits);
311 141 : n = (nbits+7)/8;
312 141 : return (n == DIM (oid_cv25519)
313 141 : && !memcmp (buf, oid_cv25519, DIM (oid_cv25519)));
314 : }
315 :
316 :
317 : /* Map the Libgcrypt ECC curve NAME to an OID. If R_NBITS is not NULL
318 : store the bit size of the curve there. Returns NULL for unknown
319 : curve names. */
320 : const char *
321 0 : openpgp_curve_to_oid (const char *name, unsigned int *r_nbits)
322 : {
323 : int i;
324 0 : unsigned int nbits = 0;
325 0 : const char *oidstr = NULL;
326 :
327 0 : if (name)
328 : {
329 0 : for (i=0; oidtable[i].name; i++)
330 0 : if (!strcmp (oidtable[i].name, name)
331 0 : || (oidtable[i].alias && !strcmp (oidtable[i].alias, name)))
332 : {
333 0 : oidstr = oidtable[i].oidstr;
334 0 : nbits = oidtable[i].nbits;
335 0 : break;
336 : }
337 0 : if (!oidtable[i].name)
338 : {
339 : /* If not found assume the input is already an OID and check
340 : whether we support it. */
341 0 : for (i=0; oidtable[i].name; i++)
342 0 : if (!strcmp (name, oidtable[i].oidstr))
343 : {
344 0 : oidstr = oidtable[i].oidstr;
345 0 : nbits = oidtable[i].nbits;
346 0 : break;
347 : }
348 : }
349 : }
350 :
351 0 : if (r_nbits)
352 0 : *r_nbits = nbits;
353 0 : return oidstr;
354 : }
355 :
356 :
357 : /* Map an OpenPGP OID to the Libgcrypt curve NAME. Returns NULL for
358 : unknown curve names. Unless CANON is set we prefer an alias name
359 : here which is more suitable for printing. */
360 : const char *
361 12 : openpgp_oid_to_curve (const char *oidstr, int canon)
362 : {
363 : int i;
364 :
365 12 : if (!oidstr)
366 0 : return NULL;
367 :
368 48 : for (i=0; oidtable[i].name; i++)
369 48 : if (!strcmp (oidtable[i].oidstr, oidstr))
370 12 : return !canon && oidtable[i].alias? oidtable[i].alias : oidtable[i].name;
371 :
372 0 : return NULL;
373 : }
374 :
375 :
376 : /* Return true if the curve with NAME is supported. */
377 : static int
378 9 : curve_supported_p (const char *name)
379 : {
380 9 : int result = 0;
381 : gcry_sexp_t keyparms;
382 :
383 9 : if (!gcry_sexp_build (&keyparms, NULL, "(public-key(ecc(curve %s)))", name))
384 : {
385 9 : result = !!gcry_pk_get_curve (keyparms, 0, NULL);
386 9 : gcry_sexp_release (keyparms);
387 : }
388 9 : return result;
389 : }
390 :
391 :
392 : /* Enumerate available and supported OpenPGP curves. The caller needs
393 : to set the integer variable at ITERP to zero and keep on calling
394 : this function until NULL is returned. */
395 : const char *
396 10 : openpgp_enum_curves (int *iterp)
397 : {
398 10 : int idx = *iterp;
399 :
400 20 : while (idx >= 0 && idx < DIM (oidtable) && oidtable[idx].name)
401 : {
402 9 : if (curve_supported_p (oidtable[idx].name))
403 : {
404 9 : *iterp = idx + 1;
405 9 : return oidtable[idx].alias? oidtable[idx].alias : oidtable[idx].name;
406 : }
407 0 : idx++;
408 : }
409 1 : *iterp = idx;
410 1 : return NULL;
411 : }
412 :
413 :
414 : /* Return the Libgcrypt name for for the gpg curve NAME if supported.
415 : * If R_ALGO is not NULL the required OpenPGP public key algo or 0 is
416 : * stored at that address. NULL is returned if the curev is not
417 : * supported. */
418 : const char *
419 0 : openpgp_is_curve_supported (const char *name, int *r_algo)
420 : {
421 : int idx;
422 :
423 0 : if (r_algo)
424 0 : *r_algo = 0;
425 0 : for (idx = 0; idx < DIM (oidtable) && oidtable[idx].name; idx++)
426 : {
427 0 : if ((!strcmp (name, oidtable[idx].name)
428 0 : || (oidtable[idx].alias && !strcmp (name, (oidtable[idx].alias))))
429 0 : && curve_supported_p (oidtable[idx].name))
430 : {
431 0 : if (r_algo)
432 0 : *r_algo = oidtable[idx].pubkey_algo;
433 0 : return oidtable[idx].name;
434 : }
435 : }
436 0 : return NULL;
437 : }
|