sm: Support generation of card-based ed25519 CSR.
[gnupg.git] / sm / misc.c
1 /* misc.c - Miscellaneous functions
2  * Copyright (C) 2004, 2009, 2011 Free Software Foundation, Inc.
3  *
4  * This file is part of GnuPG.
5  *
6  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <https://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21 #include <errno.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #ifdef HAVE_LOCALE_H
28 #include <locale.h>
29 #endif
30
31 #include "gpgsm.h"
32 #include "../common/i18n.h"
33 #include "../common/sysutils.h"
34 #include "../common/tlv.h"
35 #include "../common/sexp-parse.h"
36
37
38 /* Setup the environment so that the pinentry is able to get all
39    required information.  This is used prior to an exec of the
40    protect-tool. */
41 void
42 setup_pinentry_env (void)
43 {
44 #ifndef HAVE_W32_SYSTEM
45   char *lc;
46   const char *name, *value;
47   int iterator;
48
49   /* Try to make sure that GPG_TTY has been set.  This is needed if we
50      call for example the protect-tools with redirected stdin and thus
51      it won't be able to ge a default by itself.  Try to do it here
52      but print a warning.  */
53   value = session_env_getenv (opt.session_env, "GPG_TTY");
54   if (value)
55     gnupg_setenv ("GPG_TTY", value, 1);
56   else if (!(lc=getenv ("GPG_TTY")) || !*lc)
57     {
58       log_error (_("GPG_TTY has not been set - "
59                    "using maybe bogus default\n"));
60       lc = gnupg_ttyname (0);
61       if (!lc)
62         lc = "/dev/tty";
63       gnupg_setenv ("GPG_TTY", lc, 1);
64     }
65
66   if (opt.lc_ctype)
67     gnupg_setenv ("LC_CTYPE", opt.lc_ctype, 1);
68 #if defined(HAVE_SETLOCALE) && defined(LC_CTYPE)
69   else if ( (lc = setlocale (LC_CTYPE, "")) )
70     gnupg_setenv ("LC_CTYPE", lc, 1);
71 #endif
72
73   if (opt.lc_messages)
74     gnupg_setenv ("LC_MESSAGES", opt.lc_messages, 1);
75 #if defined(HAVE_SETLOCALE) && defined(LC_MESSAGES)
76   else if ( (lc = setlocale (LC_MESSAGES, "")) )
77     gnupg_setenv ("LC_MESSAGES", lc, 1);
78 #endif
79
80   iterator = 0;
81   while ((name = session_env_list_stdenvnames (&iterator, NULL)))
82     {
83       if (!strcmp (name, "GPG_TTY"))
84         continue;  /* Already set.  */
85       value = session_env_getenv (opt.session_env, name);
86       if (value)
87         gnupg_setenv (name, value, 1);
88     }
89
90 #endif /*!HAVE_W32_SYSTEM*/
91 }
92
93
94
95 /* Transform a sig-val style s-expression as returned by Libgcrypt to
96    one which includes an algorithm identifier encoding the public key
97    and the hash algorithm.  The public key algorithm is taken directly
98    from SIGVAL and the hash algorithm is given by MDALGO.  This is
99    required because X.509 merges the public key algorithm and the hash
100    algorithm into one OID but Libgcrypt is not aware of that.  The
101    function ignores missing parameters so that it can also be used to
102    create an siginfo value as expected by ksba_certreq_set_siginfo.
103    To create a siginfo s-expression a public-key s-expression may be
104    used instead of a sig-val.  We only support RSA for now.  */
105 gpg_error_t
106 transform_sigval (const unsigned char *sigval, size_t sigvallen, int mdalgo,
107                   unsigned char **r_newsigval, size_t *r_newsigvallen)
108 {
109   gpg_error_t err;
110   const unsigned char *buf, *tok;
111   size_t buflen, toklen;
112   int depth, last_depth1, last_depth2, pkalgo;
113   int is_pubkey = 0;
114   const unsigned char *rsa_s, *ecc_r, *ecc_s;
115   size_t rsa_s_len, ecc_r_len, ecc_s_len;
116   const char *oid;
117   gcry_sexp_t sexp;
118
119   rsa_s = ecc_r = ecc_s = NULL;
120   rsa_s_len = ecc_r_len = ecc_s_len = 0;
121
122   *r_newsigval = NULL;
123   if (r_newsigvallen)
124     *r_newsigvallen = 0;
125
126   buf = sigval;
127   buflen = sigvallen;
128   depth = 0;
129   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
130     return err;
131   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
132     return err;
133   if (tok && toklen == 7 && !memcmp ("sig-val", tok, toklen))
134     ;
135   else if (tok && toklen == 10 && !memcmp ("public-key", tok, toklen))
136     is_pubkey = 1;
137   else
138     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
139   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
140     return err;
141   if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
142     return err;
143   if (!tok)
144     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
145   if (toklen == 3 && !memcmp ("rsa", tok, 3))
146     pkalgo = GCRY_PK_RSA;
147   else if (toklen == 5 && !memcmp ("ecdsa", tok, 5))
148     pkalgo = GCRY_PK_ECC;
149   else if (toklen == 5 && !memcmp ("eddsa", tok, 5))
150     pkalgo = GCRY_PK_EDDSA;
151   else
152     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
153
154   last_depth1 = depth;
155   while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
156          && depth && depth >= last_depth1)
157     {
158       if (tok)
159         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
160       if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
161         return err;
162       if (tok && toklen == 1)
163         {
164           const unsigned char **mpi = NULL;
165           size_t *mpi_len = NULL;
166
167           switch (*tok)
168             {
169             case 's':
170               if (pkalgo == GCRY_PK_RSA)
171                 {
172                   mpi = &rsa_s;
173                   mpi_len = &rsa_s_len;
174                 }
175               else if (pkalgo == GCRY_PK_ECC || pkalgo == GCRY_PK_EDDSA)
176                 {
177                   mpi = &ecc_s;
178                   mpi_len = &ecc_s_len;
179                 }
180               break;
181
182             case 'r': mpi = &ecc_r; mpi_len = &ecc_r_len; break;
183             default:  mpi = NULL;   mpi_len = NULL; break;
184             }
185
186           if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
187             return err;
188           if (tok && mpi)
189             {
190               *mpi = tok;
191               *mpi_len = toklen;
192             }
193         }
194
195       /* Skip to the end of the list. */
196       last_depth2 = depth;
197       while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
198              && depth && depth >= last_depth2)
199         ;
200       if (err)
201         return err;
202     }
203   if (err)
204     return err;
205
206   /* Map the hash algorithm to an OID.  */
207   switch (mdalgo | (pkalgo << 8))
208     {
209     case GCRY_MD_SHA1 | (GCRY_PK_RSA << 8):
210       oid = "1.2.840.113549.1.1.5";  /* sha1WithRSAEncryption */
211       break;
212
213     case GCRY_MD_SHA256 | (GCRY_PK_RSA << 8):
214       oid = "1.2.840.113549.1.1.11"; /* sha256WithRSAEncryption */
215       break;
216
217     case GCRY_MD_SHA384 | (GCRY_PK_RSA << 8):
218       oid = "1.2.840.113549.1.1.12"; /* sha384WithRSAEncryption */
219       break;
220
221     case GCRY_MD_SHA512 | (GCRY_PK_RSA << 8):
222       oid = "1.2.840.113549.1.1.13"; /* sha512WithRSAEncryption */
223       break;
224
225     case GCRY_MD_SHA224 | (GCRY_PK_ECC << 8):
226       oid = "1.2.840.10045.4.3.1"; /* ecdsa-with-sha224 */
227       break;
228
229     case GCRY_MD_SHA256 | (GCRY_PK_ECC << 8):
230       oid = "1.2.840.10045.4.3.2"; /* ecdsa-with-sha256 */
231       break;
232
233     case GCRY_MD_SHA384 | (GCRY_PK_ECC << 8):
234       oid = "1.2.840.10045.4.3.3"; /* ecdsa-with-sha384 */
235       break;
236
237     case GCRY_MD_SHA512 | (GCRY_PK_ECC << 8):
238       oid = "1.2.840.10045.4.3.4"; /* ecdsa-with-sha512 */
239       break;
240
241     case GCRY_MD_SHA512 | (GCRY_PK_EDDSA << 8):
242       oid = "1.3.101.112"; /* ed25519 */
243       break;
244
245     default:
246       return gpg_error (GPG_ERR_DIGEST_ALGO);
247     }
248
249   if (is_pubkey)
250     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s))", oid);
251   else if (pkalgo == GCRY_PK_RSA)
252     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(s%b)))", oid,
253                            (int)rsa_s_len, rsa_s);
254   else if (pkalgo == GCRY_PK_ECC || pkalgo == GCRY_PK_EDDSA)
255     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(r%b)(s%b)))", oid,
256                            (int)ecc_r_len, ecc_r, (int)ecc_s_len, ecc_s);
257   if (err)
258     return err;
259   err = make_canon_sexp (sexp, r_newsigval, r_newsigvallen);
260   gcry_sexp_release (sexp);
261
262   return err;
263 }