File: nonce.c

package info (click to toggle)
pidgin-encryption 3.1-1
  • links: PTS
  • area: main
  • in suites: squeeze, wheezy
  • size: 2,916 kB
  • ctags: 961
  • sloc: sh: 10,460; ansic: 8,821; makefile: 376; yacc: 318
file content (128 lines) | stat: -rw-r--r-- 3,680 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*             Nonces for the Pidgin encryption plugin                      */
/*            Copyright (C) 2001-2003 William Tompkins                    */

/* This plugin is free software, distributed under the GNU General Public */
/* License.                                                               */
/* Please see the file "COPYING" distributed with this source code        */
/* for more details                                                       */
/*                                                                        */
/*                                                                        */
/*    This software is distributed in the hope that it will be useful,    */
/*   but WITHOUT ANY WARRANTY; without even the implied warranty of       */
/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU    */
/*   General Public License for more details.                             */

/*   To compile and use:                                                  */
/*     See INSTALL file.                                                  */

#include "internal.h"

#include <glib.h>

#include "debug.h"

#include "base64.h"
#include "pk11func.h"

#include "nonce.h"


static GHashTable *incoming_nonces;

static const int MaxNonceIncr = 20;

void PE_nonce_map_init() {
   incoming_nonces = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
}

int PE_nonce_str_len() {
   return (sizeof(Nonce) * 4 / 3);
}

void PE_incr_nonce(Nonce* nonce) {
   int i = sizeof(Nonce);
   unsigned char carry = 1;

   while (carry && i > 0) {
      ++((*nonce)[--i]);
      carry = (nonce[i] == 0);
   }
}

gchar* PE_nonce_to_str(Nonce* nonce) {
   char * tmp = BTOA_DataToAscii(*nonce, sizeof(Nonce));
   gchar* out = g_strdup(tmp);

   purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Built Nonce:%u:%s\n", (unsigned)sizeof(Nonce), tmp);

   PORT_Free(tmp);
   return out;
}

/* Intentionally un-optimized compare: should take constant time no matter */
/* where nonces may differ.                                                */

static int nonce_cmp(Nonce* n1, Nonce* n2) {
   int retval = 0;
   int i;
   for (i = 0; i < sizeof(Nonce); ++i) {
      if ((*n1)[i] != (*n2)[i]) retval = 1;
   }
   
   return retval;
}


void PE_str_to_nonce(Nonce* nonce, char* nonce_str) {
   unsigned int tmp_len;
   unsigned char* tmp_bin;

   tmp_bin = ATOB_AsciiToData(nonce_str, &tmp_len);
   if (tmp_len != sizeof(Nonce)) {
      PORT_Free(tmp_bin);
      memset(nonce, 0, sizeof(Nonce));
      purple_debug(PURPLE_DEBUG_ERROR, "pidgin-encryption", "Error parsing RSANSS nonce\n");
      return;
   }
   memcpy(nonce, tmp_bin, sizeof(Nonce));
   
   PORT_Free(tmp_bin);
}

gchar* PE_new_incoming_nonce(const char* name) {
   Nonce *nonce = g_malloc(sizeof(Nonce));

   SECStatus rv = PK11_GenerateRandom(*nonce, sizeof(Nonce));
   g_assert(rv == SECSuccess);

   g_hash_table_replace(incoming_nonces, g_strdup(name), nonce);   

   return PE_nonce_to_str(nonce);
}

int PE_check_incoming_nonce(const char* name, char* nonce_str) {
   Nonce new_nonce;
   Nonce* orig_nonce = g_hash_table_lookup(incoming_nonces, name);
   Nonce try_nonce;
   int i;
   
   /* purple_debug(PURPLE_DEBUG_INFO, "pidgin-encryption", "Nonce Check start\n"); */

   if (orig_nonce == 0) return 0;

   memcpy(&try_nonce, orig_nonce, sizeof(Nonce));
   
   PE_str_to_nonce(&new_nonce, nonce_str);
   
   for (i = 0; i < MaxNonceIncr; ++i) {
      if (nonce_cmp(&new_nonce, &try_nonce) == 0) {
         memcpy(orig_nonce, &try_nonce, sizeof(Nonce));
         PE_incr_nonce(orig_nonce);
         return 1;
      }
      PE_incr_nonce(&try_nonce);
   }
   
   return 0;
}