~ubuntu-branches/ubuntu/trusty/fpm2/trusty

« back to all changes in this revision

Viewing changes to src/fpm_crypt.c

  • Committer: Bazaar Package Importer
  • Author(s): Wen-Yen Chuang
  • Date: 2009-04-14 10:08:43 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20090414100843-f6l01jmsep1myiej
Tags: 0.75-1
* New upstream release
  - fix a decryption bug on big-endian machines (Closes: #516196)
  - support <DEFAULTS> category as default category (Closes: #493317)
* Update debian/copyright
* Update long description in debian/control, the default cipher is AES-256 now
* Drop transitional package "fpm". Debian Squeeze release does not need it.
* Update debian/watch
* Replace obsolete "dh_clean -k" with "dh_prep"
* Bump Standards-Version to 3.8.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* FIGARO'S PASSWORD MANAGER (FPM)
 
1
/* FIGARO'S PASSWORD MANAGER 2 (FPM2)
2
2
 * Copyright (C) 2000 John Conneely
3
 
 * 
 
3
 * Copyright (C) 2009 Aleš Koval
 
4
 *
4
5
 * FPM is open source / free software; you can redistribute it and/or modify
5
6
 * it under the terms of the GNU General Public License as published by
6
7
 * the Free Software Foundation; either version 2 of the License, or
15
16
 * along with this program; if not, write to the Free Software
16
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
17
18
 * This file contains the crypto interface for FPS.
18
 
 * 
 
19
 *
19
20
 * fpm_crypt.c - Crypto interface for FPM
20
21
 */
21
22
 
25
26
#include "fpm_crypt.h"
26
27
#include "fpm.h"
27
28
 
28
 
void (*fpm_encrypt_block) (void *c, byte *outbuf, byte *inbuf);
29
 
void (*fpm_decrypt_block) (void *c, byte *outbuf, byte *inbuf);
 
29
static fpm_cipher ciphers[] = {
 
30
    { "BLOWFISH", 16, 4 },
 
31
    { "AES-256", 32, 16 }
 
32
};
 
33
 
 
34
void (*fpm_encrypt_block) (void *c, byte *outbuf, const byte *inbuf);
 
35
void (*fpm_decrypt_block) (void *c, byte *outbuf, const byte *inbuf);
30
36
 
31
37
static size_t keylen, blocksize, contextsize;
32
38
 
33
39
static void fpm_hex_to_bin(byte* out, const gchar* in, gint len);
34
40
static void fpm_bin_to_hex(gchar* out, const byte* in, gint len);
35
41
 
36
 
void
37
 
fpm_crypt_init(gchar* password)
38
 
{
 
42
void fpm_cipher_init(char *cipher_name) {
 
43
 
 
44
    if(strcmp(cipher_name, "BLOWFISH") == 0) {
 
45
        cipher_algo = BLOWFISH;
 
46
    }
 
47
    else if(strcmp(cipher_name, "AES-256") == 0) {
 
48
        cipher_algo = AES256;
 
49
    }
 
50
 
 
51
    switch(cipher_algo)  {
 
52
        case BLOWFISH:
 
53
                if (strcmp("BLOWFISH", blowfish_get_info(4, &keylen, &blocksize,
 
54
                                             &contextsize, &fpm_setkey,
 
55
                                             &fpm_encrypt_block,
 
56
                                             &fpm_decrypt_block)))
 
57
                { g_assert_not_reached(); }
 
58
                break;
 
59
        case AES256:
 
60
                if (strcmp("AES256", rijndael_get_info(9, &keylen, &blocksize,
 
61
                                             &contextsize, &fpm_setkey,
 
62
                                             &fpm_encrypt_block,
 
63
                                             &fpm_decrypt_block)))
 
64
                { g_assert_not_reached(); }
 
65
                break;
 
66
        default:
 
67
                printf("Unknown cipher algorithm!\n");
 
68
                exit(-1);
 
69
    }
 
70
    cipher->name = ciphers[cipher_algo].name;
 
71
    cipher->hash_len = ciphers[cipher_algo].hash_len;
 
72
    cipher->salt_len = ciphers[cipher_algo].salt_len;
 
73
    cipher->keylen = keylen;
 
74
    cipher->blocksize = blocksize;
 
75
    cipher->contextsize = contextsize;
 
76
}
 
77
 
 
78
void fpm_crypt_init(gchar* password) {
39
79
  gchar *prehash1, *prehash2;
40
 
  byte *md5_1, *md5_2;
41
 
 
42
 
  if (strcmp("BLOWFISH", blowfish_get_info(4, &keylen, &blocksize,
43
 
                                             &contextsize, &fpm_setkey,
44
 
                                             &fpm_encrypt_block,
45
 
                                             &fpm_decrypt_block))) 
46
 
  {
47
 
    g_assert_not_reached();
48
 
  }
49
 
  old_context = g_malloc(contextsize);
50
 
  new_context = g_malloc(contextsize);
51
 
 
52
 
  prehash1=g_strdup_printf("%s%s", old_salt, password);
53
 
  prehash2=g_strdup_printf("%s%s", new_salt, password);
54
 
 
55
 
 
56
 
  md5_1=md5((byte *)prehash1, strlen(prehash1));
57
 
  md5_2=md5((byte *)prehash2, strlen(prehash2));
58
 
 
59
 
  fpm_setkey(old_context, md5_1, 16);
60
 
  fpm_setkey(new_context, md5_2, 16);
61
 
 
62
 
  g_free(md5_1);
63
 
  g_free(md5_2);
 
80
  byte *hash_1, *hash_2;
 
81
 
 
82
  old_context = g_malloc(cipher->contextsize);
 
83
  new_context = g_malloc(cipher->contextsize);
 
84
 
 
85
  if(cipher_algo == AES256) {
 
86
    hash_1 = g_malloc(cipher->hash_len);
 
87
    hash_2 = g_malloc(cipher->hash_len);
 
88
 
 
89
    pkcs5_pbkdf2(password, strlen(password), old_salt, cipher->salt_len, hash_1, cipher->hash_len, PBKDF2_ITERATIONS);
 
90
    pkcs5_pbkdf2(password, strlen(password), new_salt, cipher->salt_len, hash_2, cipher->hash_len, PBKDF2_ITERATIONS);
 
91
  } else {
 
92
    prehash1=g_strdup_printf("%s%s", old_salt, password);
 
93
    prehash2=g_strdup_printf("%s%s", new_salt, password);
 
94
 
 
95
    hash_1=md5((byte *)prehash1, strlen(prehash1));
 
96
    hash_2=md5((byte *)prehash2, strlen(prehash2));
 
97
  }
 
98
 
 
99
  fpm_setkey(old_context, hash_1, cipher->hash_len);
 
100
  fpm_setkey(new_context, hash_2, cipher->hash_len);
 
101
 
 
102
  wipememory(hash_1, cipher->hash_len);
 
103
  wipememory(hash_2, cipher->hash_len);
 
104
 
 
105
  g_free(hash_1);
 
106
  g_free(hash_2);
 
107
 
 
108
  if (cipher_algo == BLOWFISH) {
 
109
    wipememory(prehash1, strlen(prehash1));
 
110
    wipememory(prehash2, strlen(prehash2));
 
111
    g_free(prehash1);
 
112
    g_free(prehash2);
 
113
  }
 
114
}
 
115
 
 
116
void fpm_crypt_set_password(gchar *password) {
 
117
    gchar *prehash;
 
118
    byte *hash;
 
119
 
 
120
    new_salt = get_new_salt(cipher->salt_len);
 
121
 
 
122
    if(cipher_algo == AES256) {
 
123
        hash = g_malloc(cipher->hash_len);
 
124
        pkcs5_pbkdf2(password, strlen(password), new_salt, cipher->salt_len, hash, cipher->hash_len, PBKDF2_ITERATIONS);
 
125
    } else {
 
126
        prehash = (guchar *) g_strdup_printf("%s%s", new_salt, password);
 
127
        hash = md5(prehash, strlen((gchar *) prehash));
 
128
    }
 
129
 
 
130
    fpm_setkey(new_context, hash, cipher->hash_len);
 
131
 
 
132
    if (cipher_algo == BLOWFISH)
 
133
        wipememory(prehash, strlen(prehash));
 
134
 
 
135
    wipememory(hash, cipher->hash_len);
 
136
    g_free(hash);
64
137
}
65
138
 
66
139
static void
103
176
 
104
177
  g_assert(blocksize>0);
105
178
  num_blocks = len/blocksize;
 
179
 
106
180
  g_assert(len==num_blocks*blocksize);
107
181
  tmp=g_malloc0(len+1);
108
182
  for(b=0;b<num_blocks;b++)
110
184
    for(i=0;i<blocksize;i++) tmp[b*blocksize+i] = field[i*num_blocks+b];
111
185
  }
112
186
  memcpy(field, tmp, len);
113
 
  memset(tmp, 0, len);  
 
187
  wipememory(tmp, len);
 
188
  g_free(tmp);
114
189
}
115
190
 
116
191
static void
129
204
    for(i=0;i<blocksize;i++) tmp[i*num_blocks+b] = field[b*blocksize+i];
130
205
  }
131
206
  memcpy(field, tmp, len);
132
 
  memset(tmp, 0, len);  
 
207
  wipememory(tmp, len);
 
208
  g_free(tmp);
133
209
}
134
210
 
135
211
void
147
223
 
148
224
  /* Calculate # of blocks */
149
225
  num_blocks = len / blocksize;
150
 
  
 
226
 
151
227
  /* We assume len is multiple of blocksize */
152
228
  g_assert((len-num_blocks*blocksize)==0);
153
229
 
161
237
         (byte *)(plaintext+i*blocksize), (ciphertext+i*blocksize) );
162
238
  }
163
239
  fpm_unrotate(plaintext, len);
164
 
 
 
240
 
165
241
  g_free(ciphertext);
166
242
}
167
243
 
168
 
 
169
244
gchar*
170
245
fpm_decrypt_field_var(  void* context,
171
246
                        gchar* cipher_field)
188
263
  return(plaintext);
189
264
}
190
265
 
191
 
 
192
 
 
193
 
 
194
266
void
195
267
fpm_encrypt_field(      void* context,
196
268
                        gchar* cipher_field,
208
280
 
209
281
  /* Calculate # of blocks */
210
282
  num_blocks = len / blocksize;
211
 
  
 
283
 
212
284
  ciphertext = g_malloc(len);
213
285
 
214
286
  for(i=0; i<num_blocks; i++)
236
308
  cipher_field = g_malloc0((len*2)+1);
237
309
 
238
310
  fpm_encrypt_field(context, cipher_field, plain_field, num_blocks*blocksize);
239
 
  memset(plain_field, 0, len);
 
311
  wipememory(plain_field, len);
240
312
  g_free(plain_field);
241
313
 
242
314
  return(cipher_field);
256
328
  }
257
329
}
258
330
 
259
 
 
260
331
static void fpm_bin_to_hex(gchar* out, const byte* in, gint len)
261
332
{
262
333
  gint i, high, low;
263
334
  byte data;
264
 
  
265
335
 
266
336
  for(i=0; i<len; i++)
267
337
  {
273
343
  }
274
344
}
275
345
 
276
 
 
277
 
gchar* get_new_salt()
 
346
gchar* get_new_salt(gint len)
278
347
{
279
348
  byte* data;
280
349
  gchar* ret_val;
281
350
  FILE* rnd;
282
 
  gint len;
283
351
  size_t result;
284
352
 
285
 
  len = 4;
286
 
 
287
353
  data = g_malloc0(len+1);
288
354
  ret_val = g_malloc0(len*2+1);
289
355
  rnd=fopen("/dev/random", "r");
290
356
 
291
357
  result = fread(data, 1, len, rnd);
292
358
  fpm_bin_to_hex(ret_val, data, len);
 
359
  fclose(rnd);
293
360
  g_free(data);
294
361
  return(ret_val);
295
362
}
311
378
  GList *list;
312
379
  fpm_data *data;
313
380
 
314
 
  list=g_list_first(glb_pass_list);
315
 
  while(list!=NULL)
 
381
  list = g_list_first(glb_pass_list);
 
382
  while(list != NULL)
316
383
  {
317
384
    data = list->data;
318
385
    fpm_decrypt_field_inplace(&data->title);
324
391
 
325
392
    list=g_list_next(list);
326
393
  }
327
 
 
 
394
}
 
395
 
 
396
void fpm_decrypt_launchers() {
 
397
  GList *list;
 
398
  fpm_launcher *data;
 
399
  gchar* plaintext;
 
400
 
 
401
  list = g_list_first(glb_launcher_list);
 
402
  while(list != NULL)
 
403
  {
 
404
    data = list->data;
 
405
    fpm_decrypt_field_inplace(&data->title);
 
406
    fpm_decrypt_field_inplace(&data->cmdline);
 
407
 
 
408
    plaintext = fpm_decrypt_field_var(old_context, data->c_user);
 
409
    data->copy_user = atoi(plaintext);
 
410
 
 
411
    plaintext = fpm_decrypt_field_var(old_context, data->c_pass);
 
412
    data->copy_password = atoi(plaintext);
 
413
    g_free(data->c_pass);
 
414
 
 
415
    list = g_list_next(list);
 
416
  }
328
417
}