1 /* Nonces for the Pidgin encryption plugin */
2 /* Copyright (C) 2001-2003 William Tompkins */
3
4 /* This plugin is free software, distributed under the GNU General Public */
5 /* License. */
6 /* Please see the file "COPYING" distributed with this source code */
7 /* for more details */
8 /* */
9 /* */
10 /* This software is distributed in the hope that it will be useful, */
11 /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
12 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */
13 /* General Public License for more details. */
14
15 /* To compile and use: */
16 /* See INSTALL file. */
17
18 #include "internal.h"
19
20 #include <glib.h>
21
22 #include "debug.h"
23
24 #include "base64.h"
25 #include "pk11func.h"
26
27 #include "nonce.h"
28
29
30 static GHashTable *incoming_nonces;
31
32 static const int MaxNonceIncr = 20;
33
PE_nonce_map_init()34 void PE_nonce_map_init() {
35 incoming_nonces = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
36 }
37
PE_nonce_str_len()38 int PE_nonce_str_len() {
39 return (sizeof(Nonce) * 4 / 3);
40 }
41
PE_incr_nonce(Nonce * nonce)42 void PE_incr_nonce(Nonce* nonce) {
43 int i = sizeof(Nonce);
44 unsigned char carry = 1;
45
46 while (carry && i > 0) {
47 ++((*nonce)[--i]);
48 carry = (nonce[i] == 0);
49 }
50 }
51
PE_nonce_to_str(Nonce * nonce)52 gchar* PE_nonce_to_str(Nonce* nonce) {
53 char * tmp = BTOA_DataToAscii(*nonce, sizeof(Nonce));
54 gchar* out = g_strdup(tmp);
55
56 purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Built Nonce:%u:%s\n", (unsigned)sizeof(Nonce), tmp);
57
58 PORT_Free(tmp);
59 return out;
60 }
61
62 /* Intentionally un-optimized compare: should take constant time no matter */
63 /* where nonces may differ. */
64
nonce_cmp(Nonce * n1,Nonce * n2)65 static int nonce_cmp(Nonce* n1, Nonce* n2) {
66 int retval = 0;
67 int i;
68 for (i = 0; i < sizeof(Nonce); ++i) {
69 if ((*n1)[i] != (*n2)[i]) retval = 1;
70 }
71
72 return retval;
73 }
74
75
PE_str_to_nonce(Nonce * nonce,char * nonce_str)76 void PE_str_to_nonce(Nonce* nonce, char* nonce_str) {
77 unsigned int tmp_len;
78 unsigned char* tmp_bin;
79
80 tmp_bin = ATOB_AsciiToData(nonce_str, &tmp_len);
81 if (tmp_len != sizeof(Nonce)) {
82 PORT_Free(tmp_bin);
83 memset(nonce, 0, sizeof(Nonce));
84 purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Error parsing RSANSS nonce\n");
85 return;
86 }
87 memcpy(nonce, tmp_bin, sizeof(Nonce));
88
89 PORT_Free(tmp_bin);
90 }
91
PE_new_incoming_nonce(const char * name)92 gchar* PE_new_incoming_nonce(const char* name) {
93 Nonce *nonce = g_malloc(sizeof(Nonce));
94
95 SECStatus rv = PK11_GenerateRandom(*nonce, sizeof(Nonce));
96 g_assert(rv == SECSuccess);
97
98 g_hash_table_replace(incoming_nonces, g_strdup(name), nonce);
99
100 return PE_nonce_to_str(nonce);
101 }
102
PE_check_incoming_nonce(const char * name,char * nonce_str)103 int PE_check_incoming_nonce(const char* name, char* nonce_str) {
104 Nonce new_nonce;
105 Nonce* orig_nonce = g_hash_table_lookup(incoming_nonces, name);
106 Nonce try_nonce;
107 int i;
108
109 /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Nonce Check start\n"); */
110
111 if (orig_nonce == 0) return 0;
112
113 memcpy(&try_nonce, orig_nonce, sizeof(Nonce));
114
115 PE_str_to_nonce(&new_nonce, nonce_str);
116
117 for (i = 0; i < MaxNonceIncr; ++i) {
118 if (nonce_cmp(&new_nonce, &try_nonce) == 0) {
119 memcpy(orig_nonce, &try_nonce, sizeof(Nonce));
120 PE_incr_nonce(orig_nonce);
121 return 1;
122 }
123 PE_incr_nonce(&try_nonce);
124 }
125
126 return 0;
127 }
128
129