6f8c0fefbb69970b9e2e873c3a6170f48cd5269d
[gnuk/gnuk.git] / src / ac.c
1 /*
2  * ac.c -- Check access condition
3  *
4  * Copyright (C) 2010 Free Software Initiative of Japan
5  * Author: NIIBE Yutaka <gniibe@fsij.org>
6  *
7  * This file is a part of Gnuk, a GnuPG USB Token implementation.
8  *
9  * Gnuk is free software: you can redistribute it and/or modify it
10  * under the terms of the GNU General Public License as published by
11  * the Free Software Foundation, either version 3 of the License, or
12  * (at your option) any later version.
13  *
14  * Gnuk is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21  *
22  */
23
24 #include "config.h"
25 #include "ch.h"
26 #include "gnuk.h"
27
28 #include "polarssl/config.h"
29 #include "polarssl/sha1.h"
30
31 static uint8_t auth_status = AC_NONE_AUTHORIZED;
32
33 int
34 ac_check_status (uint8_t ac_flag)
35 {
36   if (ac_flag == AC_ALWAYS)
37     return 1;
38   else if (ac_flag == AC_NEVER)
39     return 0;
40   else
41     return (ac_flag & auth_status)? 1 : 0;
42 }
43
44 void
45 ac_reset_pso_cds (void)
46 {
47   gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING);
48   auth_status &= ~AC_PSO_CDS_AUTHORIZED;
49 }
50
51 void
52 ac_reset_other (void)
53 {
54   gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
55   gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
56   auth_status &= ~AC_OTHER_AUTHORIZED;
57 }
58
59 /*
60  * Verify for "Perform Security Operation : Compute Digital Signature"
61  */
62 int
63 verify_pso_cds (const uint8_t *pw, int pw_len)
64 {
65   int r;
66   uint8_t keystring[KEYSTRING_SIZE_PW1];
67
68   if (gpg_passwd_locked (PW_ERR_PW1))
69     return 0;
70
71   DEBUG_INFO ("verify_pso_cds\r\n");
72   DEBUG_BYTE (pw_len);
73
74   keystring[0] = pw_len;
75   sha1 (pw, pw_len, keystring+1);
76   if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
77     {
78       gpg_increment_pw_err_counter (PW_ERR_PW1);
79       return r;
80     }
81   else
82     gpg_reset_pw_err_counter (PW_ERR_PW1);
83
84   auth_status |= AC_PSO_CDS_AUTHORIZED;
85   return 1;
86 }
87
88 int
89 verify_other (const uint8_t *pw, int pw_len)
90 {
91   const uint8_t *ks_pw1;
92   uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
93
94   DEBUG_INFO ("verify_other\r\n");
95
96   if (gpg_passwd_locked (PW_ERR_PW1))
97     return 0;
98
99   ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
100   if ((ks_pw1 == NULL && pw_len == strlen (OPENPGP_CARD_INITIAL_PW1))
101       || (ks_pw1 != NULL && pw_len == ks_pw1[0]))
102     {                           /* No problem */
103       pw1_keystring[0] = pw_len;
104       sha1 (pw, pw_len, pw1_keystring+1);
105       if (gpg_do_load_prvkey (GPG_KEY_FOR_DECRYPTION, BY_USER,
106                               pw1_keystring + 1) < 0)
107         goto error;
108
109       if (gpg_do_load_prvkey (GPG_KEY_FOR_AUTHENTICATION, BY_USER,
110                               pw1_keystring + 1) < 0)
111         goto error;
112
113       /* Reset counter as it's success now */
114       gpg_reset_pw_err_counter (PW_ERR_PW1);
115       auth_status |= AC_OTHER_AUTHORIZED;
116       return 1;
117     }
118   else
119     {
120     error:
121       gpg_increment_pw_err_counter (PW_ERR_PW1);
122       return 0;
123     }
124 }
125
126 /*
127  * For keystring of PW3, we use SALT+ITER+MD format
128  */
129
130 static uint32_t
131 decode_iterate_count (uint8_t x)
132 {
133   return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
134 }
135
136 static void
137 calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
138          uint8_t md[KEYSTRING_MD_SIZE])
139 {
140   sha1_context sha1_ctx;
141
142   sha1_starts (&sha1_ctx);
143
144   while (count > pw_len + 8)
145     {
146       sha1_update (&sha1_ctx, salt, 8);
147       sha1_update (&sha1_ctx, pw, pw_len);
148       count -= pw_len + 8;
149     }
150
151   if (count < 8)
152     sha1_update (&sha1_ctx, salt, count);
153   else
154     {
155       sha1_update (&sha1_ctx, salt, 8);
156       count -= 8;
157       sha1_update (&sha1_ctx, pw, count);
158     }
159
160   sha1_finish (&sha1_ctx, md);
161   memset (&sha1_ctx, 0, sizeof (sha1_ctx));
162 }
163
164 int
165 verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
166 {
167   const uint8_t *pw3_keystring;
168   int pw_len;
169
170   if (gpg_passwd_locked (PW_ERR_PW3))
171     return 0;
172
173   pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
174   if (pw3_keystring != NULL)
175     {
176       int count;
177       uint8_t md[KEYSTRING_MD_SIZE];
178       const uint8_t *salt;
179
180       pw_len = pw3_keystring[0];
181       if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
182         goto failure;
183
184       salt = &pw3_keystring[1];
185       count = decode_iterate_count (pw3_keystring[1+8]);
186       calc_md (count, salt, pw, pw_len, md);
187
188       if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
189         {
190         failure:
191           gpg_increment_pw_err_counter (PW_ERR_PW3);
192           return -1;
193         }
194       else
195         /* OK, the user is now authenticated */
196         gpg_reset_pw_err_counter (PW_ERR_PW3);
197     }
198   else
199     /* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
200     {
201       if ((pw_len_known >=0
202            && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3))
203           || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3)
204           || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3,
205                       strlen (OPENPGP_CARD_INITIAL_PW3)) != 0)
206         /* It is failure, but we don't try to lock for the case of empty PW3 */
207         return -1;
208
209       pw_len = strlen (OPENPGP_CARD_INITIAL_PW3);
210     }
211
212   return pw_len;
213 }
214
215 void
216 gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
217 {
218   uint8_t ks[KEYSTRING_SIZE_PW3];
219   uint32_t random;
220
221   ks[0] = newpw_len;
222   random = get_random ();
223   memcpy (&ks[1], &random, sizeof (random));
224   random = get_random ();
225   memcpy (&ks[5], &random, sizeof (random));
226   ks[9] = 0x60;                 /* 65536 iterations */
227
228   calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
229   gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
230 }
231
232 uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
233
234 int
235 verify_admin (const uint8_t *pw, int pw_len)
236 {
237   int r;
238
239   r = verify_admin_0 (pw, pw_len, pw_len);
240   if (r <= 0)
241     return r;
242
243   sha1 (pw, pw_len, keystring_md_pw3);
244   auth_status |= AC_ADMIN_AUTHORIZED;
245   return 1;
246 }
247
248 void
249 ac_reset_admin (void)
250 {
251   memset (keystring_md_pw3, 0, KEYSTRING_MD_SIZE);
252   auth_status &= ~AC_ADMIN_AUTHORIZED;
253 }
254
255 void
256 ac_fini (void)
257 {
258   auth_status = AC_NONE_AUTHORIZED;
259   gpg_do_clear_prvkey (GPG_KEY_FOR_SIGNING);
260   gpg_do_clear_prvkey (GPG_KEY_FOR_DECRYPTION);
261   gpg_do_clear_prvkey (GPG_KEY_FOR_AUTHENTICATION);
262 }