works now again
[gnuk/gnuk.git] / src / ac.c
1 /*
2  * ac.c -- Check access condition
3  */
4
5 #include "config.h"
6 #include "ch.h"
7 #include "gnuk.h"
8
9 #include "polarssl/config.h"
10 #include "polarssl/sha1.h"
11
12 static uint8_t auth_status = AC_NONE_AUTHORIZED;
13
14 int
15 ac_check_status (uint8_t ac_flag)
16 {
17   if (ac_flag == AC_ALWAYS)
18     return 1;
19   else if (ac_flag == AC_NEVER)
20     return 0;
21   else
22     return (ac_flag & auth_status)? 1 : 0;
23 }
24
25 int
26 verify_pso_cds (const uint8_t *pw, int pw_len)
27 {
28   int r;
29   const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
30   uint8_t keystring[KEYSTRING_SIZE_PW1];
31   uint8_t pwsb[SIZE_PW_STATUS_BYTES];
32
33   if (pw_status_bytes == NULL
34       || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
35     return 0;
36
37   keystring[0] = pw_len;
38   sha1 (pw, pw_len, keystring+1);
39   memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
40   if ((r = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNATURE, 1, keystring+1)) < 0)
41     {
42       pwsb[PW_STATUS_PW1]--;
43       gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
44       return r;
45     }
46   else
47     {
48       pwsb[PW_STATUS_PW1] = 3;
49       gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
50     }
51
52   auth_status |= AC_PSO_CDS_AUTHORIZED;
53   return 1;
54 }
55
56 void
57 ac_reset_pso_cds (void)
58 {
59   auth_status &= ~AC_PSO_CDS_AUTHORIZED;
60 }
61
62 int
63 verify_pso_other (const uint8_t *pw, int pw_len)
64 {
65   int r;
66   const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
67   uint8_t keystring[KEYSTRING_SIZE_PW1];
68   uint8_t pwsb[SIZE_PW_STATUS_BYTES];
69
70   if (pw_status_bytes == NULL
71       || pw_status_bytes[PW_STATUS_PW1] == 0) /* locked */
72     return 0;
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_DECRYPT, 1, keystring+1)) < 0)
78     {
79       pwsb[PW_STATUS_PW1]--;
80       gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
81       return r;
82     }
83   else
84     {
85       pwsb[PW_STATUS_PW1] = 3;
86       gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
87     }
88
89   auth_status |= AC_PSO_OTHER_AUTHORIZED;
90   return 1;
91 }
92
93 /*
94  * For keystring of PW3, we use SALT+ITER+MD format
95  */
96 static sha1_context sha1_ctx;
97
98 static uint32_t
99 decode_iterate_count (uint8_t x)
100 {
101   return (16UL + ((x) & 15)) << (((x) >> 4) + 6);
102 }
103
104 static void
105 calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
106          uint8_t md[KEYSTRING_MD_SIZE])
107 {
108   sha1_starts (&sha1_ctx);
109
110   while (count > pw_len + 8)
111     {
112       sha1_update (&sha1_ctx, salt, 8);
113       sha1_update (&sha1_ctx, pw, pw_len);
114       count -= pw_len + 8;
115     }
116
117   if (count < 8)
118     sha1_update (&sha1_ctx, salt, count);
119   else
120     {
121       sha1_update (&sha1_ctx, salt, 8);
122       count -= 8;
123       sha1_update (&sha1_ctx, pw, count);
124     }
125
126   sha1_finish (&sha1_ctx, md);
127   memset (&sha1_ctx, 0, sizeof (sha1_ctx));
128 }
129
130 int
131 verify_admin_0 (const uint8_t *pw, int buf_len, int pw_len_known)
132 {
133   const uint8_t *pw3_keystring;
134   const uint8_t *pw_status_bytes = gpg_do_read_simple (GNUK_DO_PW_STATUS);
135   int pw_len;
136
137   if (pw_status_bytes == NULL
138       || pw_status_bytes[PW_STATUS_PW3] == 0) /* locked */
139     return 0;
140
141   pw3_keystring = gpg_do_read_simple (GNUK_DO_KEYSTRING_PW3);
142   if (pw3_keystring != NULL)
143     {
144       int count;
145       uint8_t md[KEYSTRING_MD_SIZE];
146       const uint8_t *salt;
147       uint8_t pwsb[SIZE_PW_STATUS_BYTES];
148
149       pw_len = pw3_keystring[0];
150       if ((pw_len_known >= 0 && pw_len_known != pw_len) || pw_len < buf_len)
151         goto failure;
152
153       salt = &pw3_keystring[1];
154       count = decode_iterate_count (pw3_keystring[1+8]);
155       calc_md (count, salt, pw, pw_len, md);
156       memcpy (pwsb, pw_status_bytes, SIZE_PW_STATUS_BYTES);
157
158       if (memcmp (md, &pw3_keystring[1+8+1], KEYSTRING_MD_SIZE) != 0)
159         {
160         failure:
161           pwsb[PW_STATUS_PW3]--;
162           gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
163           return -1;
164         }
165       else
166         {                      /* OK, the user is now authenticated */
167           pwsb[PW_STATUS_PW3] = 3;
168           gpg_do_write_simple (GNUK_DO_PW_STATUS, pwsb, SIZE_PW_STATUS_BYTES);
169         }
170     }
171   else
172     /* For empty PW3, pass phrase should be "12345678" */
173     {
174       if ((pw_len_known >=0 && pw_len_known != 8)
175           || buf_len < 8 || strncmp ((const char *)pw, "12345678", 8) != 0)
176         /* It is failure, but we don't try to lock for the case of empty PW3 */
177         return -1;
178
179       pw_len = 8;
180     }
181
182   return pw_len;
183 }
184
185 void
186 gpg_set_pw3 (const uint8_t *newpw, int newpw_len)
187 {
188   uint8_t ks[KEYSTRING_SIZE_PW3];
189   uint32_t random;
190
191   ks[0] = newpw_len;
192   random = get_random ();
193   memcpy (&ks[1], &random, sizeof (random));
194   random = get_random ();
195   memcpy (&ks[5], &random, sizeof (random));
196   ks[9] = 0x60;                 /* 65536 iterations */
197
198   calc_md (65536, &ks[1], newpw, newpw_len, &ks[10]);
199   gpg_do_write_simple (GNUK_DO_KEYSTRING_PW3, ks, KEYSTRING_SIZE_PW3);
200 }
201
202 uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
203
204 int
205 verify_admin (const uint8_t *pw, int pw_len)
206 {
207   int r;
208
209   r = verify_admin_0 (pw, pw_len, pw_len);
210   if (r <= 0)
211     return r;
212
213   sha1 (pw, pw_len, keystring_md_pw3);
214   auth_status |= AC_ADMIN_AUTHORIZED;
215   return 1;
216 }