added copyright notice to ac.c and fix expr.
[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   auth_status &= ~AC_PSO_CDS_AUTHORIZED;
48 }
49
50 uint8_t pw1_keystring[KEYSTRING_SIZE_PW1];
51
52 void
53 ac_reset_pso_other (void)
54 {
55   memset (pw1_keystring, 0, KEYSTRING_SIZE_PW1);
56   auth_status &= ~AC_PSO_OTHER_AUTHORIZED;
57 }
58
59 int
60 verify_pso_cds (const uint8_t *pw, int pw_len)
61 {
62   int r;
63   const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
64   uint8_t keystring[KEYSTRING_SIZE_PW1];
65   uint8_t pwsb[SIZE_PW_STATUS_BYTES];
66
67   if (pw_status_bytes == NULL
68       || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
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   memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
77   if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring+1)) < 0)
78     {
79       pwsb[PW_STATUS_PW1]--;
80       gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
81       return r;
82     }
83   else if (pwsb[PW_STATUS_PW1] != 3)
84     {
85       pwsb[PW_STATUS_PW1] = 3;
86       gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
87     }
88
89   auth_status |= AC_PSO_CDS_AUTHORIZED;
90   return 1;
91 }
92
93 int
94 verify_pso_other (const uint8_t *pw, int pw_len)
95 {
96   const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
97   uint8_t pwsb[SIZE_PW_STATUS_BYTES];
98   const uint8_t *ks_pw1;
99
100   DEBUG_INFO ("verify_pso_other\r\n");
101
102   if (pw_status_bytes == NULL
103       || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
104     return 0;
105
106   memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
107
108   /*
109    * We check only the length of password string now.
110    * Real check is defered to decrypt/authenticate routines.
111    */
112   ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
113   if ((ks_pw1 == NULL && pw_len == strlen (OPENPGP_CARD_INITIAL_PW1))
114       || (ks_pw1 != NULL && pw_len == ks_pw1[0]))
115     {                           /* No problem */
116       /*
117        * We don't reset pwsb[PW_STATUS_PW1] here.
118        * Because password may be wrong.
119        */
120       pw1_keystring[0] = pw_len;
121       sha1 (pw, pw_len, pw1_keystring+1);
122       auth_status |= AC_PSO_OTHER_AUTHORIZED;
123       return 1;
124     }
125   else
126     {
127       pwsb[PW_STATUS_PW1]--;
128       gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
129       return 0;
130     }
131 }
132
133 /*
134  * For keystring of PW3, we use SALT+ITER+MD format
135  */
136
137 static uint32_t
138 decode_iterate_count (uint8_t x)
139 {
140   return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
141 }
142
143 static void
144 calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
145          uint8_t md[KEYSTRING_MD_SIZE])
146 {
147   sha1_context sha1_ctx;
148
149   sha1_starts (&sha1_ctx);
150
151   while (count > pw_len + 8)
152     {
153       sha1_update (&sha1_ctx, salt, 8);
154       sha1_update (&sha1_ctx, pw, pw_len);
155       count -= pw_len + 8;
156     }
157
158   if (count < 8)
159     sha1_update (&sha1_ctx, salt, count);
160   else
161     {
162       sha1_update (&sha1_ctx, salt, 8);
163       count -= 8;
164       sha1_update (&sha1_ctx, pw, count);
165     }
166
167   sha1_finish (&sha1_ctx, md);
168   memset (&sha1_ctx, 0, sizeof (sha1_ctx));
169 }
170
171 int
172 verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
173 {
174   const uint8_t *pw3_keystring;
175   const uint8_t *pw_status_bytes = gpg_do_read_simple (NR_DO_PW_STATUS);
176   int pw_len;
177
178   if (pw_status_bytes == NULL
179       || pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
180     return 0;
181
182   pw3_keystring = gpg_do_read_simple (NR_DO_KEYSTRING_PW3);
183   if (pw3_keystring != NULL)
184     {
185       int count;
186       uint8_t md[KEYSTRING_MD_SIZE];
187       const uint8_t *salt;
188       uint8_t pwsb[SIZE_PW_STATUS_BYTES];
189
190       pw_len = pw3_keystring[0];
191       if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
192         goto failure;
193
194       salt = &pw3_keystring[1];
195       count = decode_iterate_count (pw3_keystring[1+8]);
196       calc_md (count, salt, pw, pw_len, md);
197       memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
198
199       if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
200         {
201         failure:
202           pwsb[PW_STATUS_PW3]--;
203           gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
204           return -1;
205         }
206       else if (pwsb[PW_STATUS_PW3] != 3)
207         {                      /* OK, the user is now authenticated */
208           pwsb[PW_STATUS_PW3] = 3;
209           gpg_do_write_simple (NR_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
210         }
211     }
212   else
213     /* For empty PW3, pass phrase should be OPENPGP_CARD_INITIAL_PW3 */
214     {
215       if ((pw_len_known >=0 && pw_len_known != strlen (OPENPGP_CARD_INITIAL_PW3))
216           || buf_len < (int)strlen (OPENPGP_CARD_INITIAL_PW3)
217           || strncmp ((const char *)pw, OPENPGP_CARD_INITIAL_PW3,
218                       strlen (OPENPGP_CARD_INITIAL_PW3)) != 0)
219         /* It is failure, but we don't try to lock for the case of empty PW3 */
220         return -1;
221
222       pw_len = 8;
223     }
224
225   return pw_len;
226 }
227
228 void
229 gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
230 {
231   uint8_t ks[KEYSTRING_SIZE_PW3];
232   uint32_t random;
233
234   ks[0] = newpw_len;
235   random = get_random ();
236   memcpy (&ks[1], &random, sizeof (random));
237   random = get_random ();
238   memcpy (&ks[5], &random, sizeof (random));
239   ks[9] = 0x60;                 /* 65536 iterations */
240
241   calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
242   gpg_do_write_simple (NR_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
243 }
244
245 uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
246
247 int
248 verify_admin (const uint8_t *pw, int pw_len)
249 {
250   int r;
251
252   r = verify_admin_0 (pw, pw_len, pw_len);
253   if (r <= 0)
254     return r;
255
256   sha1 (pw, pw_len, keystring_md_pw3);
257   auth_status |= AC_ADMIN_AUTHORIZED;
258   return 1;
259 }