chiark / gitweb /
server/tests.at (AWAIT_KXDONE): Ignore the correct server messages.
[tripe] / server / chal.c
1 /* -*-c-*-
2  *
3  * Cryptographic challenges
4  *
5  * (c) 2005 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Trivial IP Encryption (TrIPE).
11  *
12  * TrIPE is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version.
16  *
17  * TrIPE is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with TrIPE; if not, write to the Free Software Foundation,
24  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25  */
26
27 /*----- Header files ------------------------------------------------------*/
28
29 #include "tripe.h"
30
31 /*----- Static variables --------------------------------------------------*/
32
33 static gmac *mac;
34 static uint32 oseq;
35 static seqwin iseq;
36
37 /*----- Main code ---------------------------------------------------------*/
38
39 /* --- @c_genkey@ --- *
40  *
41  * Arguments:   ---
42  *
43  * Returns:     ---
44  *
45  * Use:         Generates a new challenge key.
46  */
47
48 static void c_genkey(void)
49 {
50   if (mac && GM_CLASS(mac) == master->algs.m && oseq < 0x07ffffff) return;
51   if (mac) GM_DESTROY(mac);
52   assert(master->algs.mksz < sizeof(buf_t));
53   rand_get(RAND_GLOBAL, buf_t, master->algs.mksz);
54   mac = GM_KEY(master->algs.m, buf_t, master->algs.mksz);
55   oseq = 0;
56   seq_reset(&iseq);
57   IF_TRACING(T_CHAL, {
58     trace(T_CHAL, "chal: generated new challenge key");
59     trace_block(T_CRYPTO, "chal: new key", buf_t, master->algs.mksz);
60   })
61 }
62
63 /* --- @c_new@ --- *
64  *
65  * Arguments:   @buf *b@ = where to put the challenge
66  *
67  * Returns:     Zero if OK, nonzero on error.
68  *
69  * Use:         Issues a new challenge.
70  */
71
72 int c_new(buf *b)
73 {
74   octet *p;
75   ghash *h;
76
77   c_genkey();
78   p = BCUR(b);
79   if (buf_putu32(b, oseq++)) return (-1);
80   h = GM_INIT(mac);
81   GH_HASH(h, p, BCUR(b) - p);
82   buf_put(b, GH_DONE(h, 0), master->algs.tagsz);
83   GH_DESTROY(h);
84   if (BBAD(b)) return (-1);
85   IF_TRACING(T_CHAL, {
86     trace(T_CHAL, "chal: issuing challenge %lu", (unsigned long)(oseq - 1));
87     trace_block(T_CRYPTO, "chal: challenge block", p, BCUR(b) - p);
88   })
89   return (0);
90 }
91
92 /* --- @c_check@ --- *
93  *
94  * Arguments:   @buf *b@ = where to find the challenge
95  *
96  * Returns:     Zero if OK, nonzero if it didn't work.
97  *
98  * Use:         Checks a challenge.  On failure, the buffer is broken.
99  */
100
101 int c_check(buf *b)
102 {
103   const octet *p;
104   size_t sz = 4 + master->algs.tagsz;
105   uint32 seq;
106   ghash *h;
107   int ok;
108
109   if ((p = buf_get(b, sz)) == 0) {
110     a_warn("CHAL", "invalid-challenge", A_END);
111     goto fail;
112   }
113   IF_TRACING(T_CHAL, trace_block(T_CRYPTO, "chal: check challenge", p, sz); )
114   if (!mac) {
115     a_warn("CHAL", "impossible-challenge", A_END);
116     goto fail;
117   }
118   h = GM_INIT(mac);
119   GH_HASH(h, p, 4);
120   ok = ct_memeq(GH_DONE(h, 0), p + 4, master->algs.tagsz);
121   GH_DESTROY(h);
122   if (!ok) {
123     a_warn("CHAL", "incorrect-tag", A_END);
124     goto fail;
125   }
126   seq = LOAD32(p);
127   if (seq_check(&iseq, seq, "CHAL"))
128     goto fail;
129   T( trace(T_CHAL, "chal: checked challenge %lu", (unsigned long)seq); )
130   return (0);
131
132 fail:
133   buf_break(b);
134   return (-1);
135 }
136
137 /*----- That's all, folks -------------------------------------------------*/