9bf528513162bf387053f43fc492ef52162533f8
[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
150     return gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
151
152   last_depth1 = depth;
153   while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
154          && depth && depth >= last_depth1)
155     {
156       if (tok)
157         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
158       if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
159         return err;
160       if (tok && toklen == 1)
161         {
162           const unsigned char **mpi = NULL;
163           size_t *mpi_len = NULL;
164
165           switch (*tok)
166             {
167             case 's':
168               if (pkalgo == GCRY_PK_RSA)
169                 {
170                   mpi = &rsa_s;
171                   mpi_len = &rsa_s_len;
172                 }
173               else if (pkalgo == GCRY_PK_ECC)
174                 {
175                   mpi = &ecc_s;
176                   mpi_len = &ecc_s_len;
177                 }
178               break;
179
180             case 'r': mpi = &ecc_r; mpi_len = &ecc_r_len; break;
181             default:  mpi = NULL;   mpi_len = NULL; break;
182             }
183
184           if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
185             return err;
186           if (tok && mpi)
187             {
188               *mpi = tok;
189               *mpi_len = toklen;
190             }
191         }
192
193       /* Skip to the end of the list. */
194       last_depth2 = depth;
195       while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
196              && depth && depth >= last_depth2)
197         ;
198       if (err)
199         return err;
200     }
201   if (err)
202     return err;
203
204   /* Map the hash algorithm to an OID.  */
205   switch (mdalgo | (pkalgo << 8))
206     {
207     case GCRY_MD_SHA1 | (GCRY_PK_RSA << 8):
208       oid = "1.2.840.113549.1.1.5";  /* sha1WithRSAEncryption */
209       break;
210
211     case GCRY_MD_SHA256 | (GCRY_PK_RSA << 8):
212       oid = "1.2.840.113549.1.1.11"; /* sha256WithRSAEncryption */
213       break;
214
215     case GCRY_MD_SHA384 | (GCRY_PK_RSA << 8):
216       oid = "1.2.840.113549.1.1.12"; /* sha384WithRSAEncryption */
217       break;
218
219     case GCRY_MD_SHA512 | (GCRY_PK_RSA << 8):
220       oid = "1.2.840.113549.1.1.13"; /* sha512WithRSAEncryption */
221       break;
222
223     case GCRY_MD_SHA224 | (GCRY_PK_ECC << 8):
224       oid = "1.2.840.10045.4.3.1"; /* ecdsa-with-sha224 */
225       break;
226
227     case GCRY_MD_SHA256 | (GCRY_PK_ECC << 8):
228       oid = "1.2.840.10045.4.3.2"; /* ecdsa-with-sha256 */
229       break;
230
231     case GCRY_MD_SHA384 | (GCRY_PK_ECC << 8):
232       oid = "1.2.840.10045.4.3.3"; /* ecdsa-with-sha384 */
233       break;
234
235     case GCRY_MD_SHA512 | (GCRY_PK_ECC << 8):
236       oid = "1.2.840.10045.4.3.4"; /* ecdsa-with-sha512 */
237       break;
238
239     default:
240       return gpg_error (GPG_ERR_DIGEST_ALGO);
241     }
242
243   if (is_pubkey)
244     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s))", oid);
245   else if (pkalgo == GCRY_PK_RSA)
246     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(s%b)))", oid,
247                            (int)rsa_s_len, rsa_s);
248   else if (pkalgo == GCRY_PK_ECC)
249     err = gcry_sexp_build (&sexp, NULL, "(sig-val(%s(r%b)(s%b)))", oid,
250                            (int)ecc_r_len, ecc_r, (int)ecc_s_len, ecc_s);
251   if (err)
252     return err;
253   err = make_canon_sexp (sexp, r_newsigval, r_newsigvallen);
254   gcry_sexp_release (sexp);
255
256   return err;
257 }