projects
/
u
/
mdw
/
catacomb
/ commitdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
| commitdiff |
tree
raw
|
patch
|
inline
| side by side (parent:
bc985ce
)
INCOMPATIBLE CHANGE. Use proper authentication on encrypted keys.
author
mdw
<mdw>
Sat, 27 Mar 2004 00:04:19 +0000
(
00:04
+0000)
committer
mdw
<mdw>
Sat, 27 Mar 2004 00:04:19 +0000
(
00:04
+0000)
key-pass.c
patch
|
blob
|
blame
|
history
diff --git
a/key-pass.c
b/key-pass.c
index
b6bc73d
..
3785765
100644
(file)
--- a/
key-pass.c
+++ b/
key-pass.c
@@
-1,6
+1,6
@@
/* -*-c-*-
*
/* -*-c-*-
*
- * $Id: key-pass.c,v 1.
2 2000/06/17 11:26:35
mdw Exp $
+ * $Id: key-pass.c,v 1.
3 2004/03/27 00:04:19
mdw Exp $
*
* Encrypting keys with passphrases
*
*
* Encrypting keys with passphrases
*
@@
-30,6
+30,9
@@
/*----- Revision history --------------------------------------------------*
*
* $Log: key-pass.c,v $
/*----- Revision history --------------------------------------------------*
*
* $Log: key-pass.c,v $
+ * Revision 1.3 2004/03/27 00:04:19 mdw
+ * INCOMPATIBLE CHANGE. Use proper authentication on encrypted keys.
+ *
* Revision 1.2 2000/06/17 11:26:35 mdw
* `rand_getgood' is deprecated.
*
* Revision 1.2 2000/06/17 11:26:35 mdw
* `rand_getgood' is deprecated.
*
@@
-49,9
+52,22
@@
#include "blowfish-cbc.h"
#include "rmd160.h"
#include "blowfish-cbc.h"
#include "rmd160.h"
+#include "rmd160-mgf.h"
+#include "rmd160-hmac.h"
/*----- Main code ---------------------------------------------------------*/
/*----- Main code ---------------------------------------------------------*/
+/* --- Format --- *
+ *
+ * Choose a random 160-bit string %$R$%. Take the passphrase %$P$%, and
+ * the message %$m$%. Now, compute %$K_E \cat K_T = H(R \cat P)$%,
+ * %$y_0 = E_{K_E}(m)$% and %$\tau = T_{K_T}(y_0)$%. The ciphertext is
+ * %$y = N \cat \tau \cat y_0$%.
+ *
+ * This is not the original format. The original format was insecure, and
+ * has been replaced incompatibly.
+ */
+
/* --- @key_plock@ --- *
*
* Arguments: @const char *tag@ = tag to use for passphrase
/* --- @key_plock@ --- *
*
* Arguments: @const char *tag@ = tag to use for passphrase
@@
-66,7
+82,9
@@
int key_plock(const char *tag, key_data *k, key_data *kt)
{
dstr d = DSTR_INIT;
int key_plock(const char *tag, key_data *k, key_data *kt)
{
dstr d = DSTR_INIT;
- octet hash[RMD160_HASHSZ];
+ octet b[RMD160_HASHSZ * 2];
+ octet *m;
+ size_t msz;
char buf[256];
/* --- Sanity check --- */
char buf[256];
/* --- Sanity check --- */
@@
-74,50
+92,61
@@
int key_plock(const char *tag, key_data *k, key_data *kt)
assert(((void)"Key data is already encrypted",
(k->e & KF_ENCMASK) != KENC_ENCRYPT));
assert(((void)"Key data is already encrypted",
(k->e & KF_ENCMASK) != KENC_ENCRYPT));
- /* --- Read the passphrase --- */
-
- if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf)))
- return (-1);
+ /* --- Format the stuff in the buffer --- */
- /* --- Extract the key data --- *
- *
- * On the front, put four random bytes to act as a passphrase salt (which
- * remain in the clear), and four zero bytes to be able to spot duff
- * passphrases when unlocking.
- */
-
- DENSURE(&d, 8);
- rand_get(RAND_GLOBAL, d.buf, 4);
- memset(d.buf + 4, 0, 4);
- d.len += 8;
+ DENSURE(&d, RMD160_HASHSZ * 2);
+ rand_get(RAND_GLOBAL, d.buf, RMD160_HASHSZ);
+ d.len += RMD160_HASHSZ * 2;
key_encode(k, &d, 0);
if (k == kt)
key_destroy(k);
key_encode(k, &d, 0);
if (k == kt)
key_destroy(k);
+ m = (octet *)d.buf + RMD160_HASHSZ * 2;
+ msz = d.len - RMD160_HASHSZ * 2;
- /* --- Hash the passphrase into a key --- */
+ /* --- Read the passphrase --- */
+
+ if (passphrase_read(tag, PMODE_VERIFY, buf, sizeof(buf))) {
+ dstr_destroy(&d);
+ return (-1);
+ }
+
+ /* --- Hash the passphrase to make a key --- */
{
{
- rmd160_
ctx h
;
- rmd160_
init(&h
);
- rmd160_
hash(&h, d.buf, 4
);
- rmd160_
hash(&h
, buf, strlen(buf));
- rmd160_
done(&h, hash
);
- BURN(
h
);
+ rmd160_
mgfctx r
;
+ rmd160_
mgfkeybegin(&r
);
+ rmd160_
mgfkeyadd(&r, d.buf, RMD160_HASHSZ
);
+ rmd160_
mgfkeyadd(&r
, buf, strlen(buf));
+ rmd160_
mgfencrypt(&r, 0, b, sizeof(b)
);
+ BURN(
r
);
BURN(buf);
}
BURN(buf);
}
- /* --- Encrypt the
key data
--- */
+ /* --- Encrypt the
plaintext
--- */
{
blowfish_cbcctx c;
{
blowfish_cbcctx c;
- blowfish_cbcinit(&c, hash, sizeof(hash), 0);
- blowfish_cbcencrypt(&c, d.buf + 4, d.buf + 4, d.len - 4);
- BURN(hash);
+ blowfish_cbcinit(&c, b, RMD160_HASHSZ, 0);
+ blowfish_cbcencrypt(&c, m, m, msz);
BURN(c);
}
BURN(c);
}
- /* --- Put the key data back in the key --- */
+ /* --- MAC the ciphertext --- */
+
+ {
+ rmd160_mackey mk;
+ rmd160_macctx mc;
+ rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+ rmd160_macinit(&mc, &mk);
+ rmd160_machash(&mc, m, msz);
+ rmd160_macdone(&mc, d.buf + RMD160_HASHSZ);
+ BURN(mk);
+ BURN(mc);
+ }
+
+ /* --- Done --- */
+ BURN(b);
key_encrypted(kt, d.buf, d.len);
dstr_destroy(&d);
return (0);
key_encrypted(kt, d.buf, d.len);
dstr_destroy(&d);
return (0);
@@
-136,7
+165,7
@@
int key_plock(const char *tag, key_data *k, key_data *kt)
int key_punlock(const char *tag, key_data *k, key_data *kt)
{
int key_punlock(const char *tag, key_data *k, key_data *kt)
{
- octet
hash[RMD160_HASHSZ
];
+ octet
b[RMD160_HASHSZ * 2
];
char buf[256];
octet *p;
size_t sz;
char buf[256];
octet *p;
size_t sz;
@@
-146,31
+175,27
@@
int key_punlock(const char *tag, key_data *k, key_data *kt)
assert(((void)"Key data isn't encrypted",
(k->e & KF_ENCMASK) == KENC_ENCRYPT));
assert(((void)"Key data isn't encrypted",
(k->e & KF_ENCMASK) == KENC_ENCRYPT));
- /* ---
Fetch the passphrase
--- */
+ /* ---
Allocate a destination buffer
--- */
- if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
- goto fail_0;
+ if (k->u.k.sz < RMD160_HASHSZ * 2)
+ return (-1);;
+ sz = k->u.k.sz - RMD160_HASHSZ * 2;
+ p = xmalloc(k->u.k.sz);
- /* --- Allocate a destination buffer --- *
- *
- * Minimum size for a key is four bytes salt, four bytes zeroes, two bytes
- * type, and two bytes length, making a total of twelve.
- */
+ /* --- Fetch the passphrase --- */
- if (k->u.k.sz < 12)
- goto fail_0;
- sz = k->u.k.sz - 4;
- p = xmalloc(k->u.k.sz);
+ if (passphrase_read(tag, PMODE_READ, buf, sizeof(buf)))
+ goto fail;
- /* --- Hash the passphrase --- */
+ /* --- Hash the passphrase
to make a key
--- */
{
{
- rmd160_
ctx h
;
- rmd160_
init(&h
);
- rmd160_
hash(&h, k->u.k.k, 4
);
- rmd160_
hash(&h
, buf, strlen(buf));
- rmd160_
done(&h, hash
);
- BURN(
h
);
+ rmd160_
mgfctx r
;
+ rmd160_
mgfkeybegin(&r
);
+ rmd160_
mgfkeyadd(&r, k->u.k.k, RMD160_HASHSZ
);
+ rmd160_
mgfkeyadd(&r
, buf, strlen(buf));
+ rmd160_
mgfencrypt(&r, 0, b, sizeof(b)
);
+ BURN(
r
);
BURN(buf);
}
BURN(buf);
}
@@
-178,14
+203,26
@@
int key_punlock(const char *tag, key_data *k, key_data *kt)
{
blowfish_cbcctx c;
{
blowfish_cbcctx c;
- blowfish_cbcinit(&c, hash, sizeof(hash), 0);
- blowfish_cbcdecrypt(&c, k->u.k.k + 4, p, sz);
- BURN(hash);
+ blowfish_cbcinit(&c, b, sizeof(b), 0);
+ blowfish_cbcdecrypt(&c, k->u.k.k + RMD160_HASHSZ, p, sz);
BURN(c);
BURN(c);
- if (LOAD32(p) != 0) {
+ }
+
+ /* --- Verify the MAC --- */
+
+ {
+ rmd160_mackey mk;
+ rmd160_macctx mc;
+ rmd160_hmacinit(&mk, b + RMD160_HASHSZ, RMD160_HASHSZ);
+ rmd160_macinit(&mc, &mk);
+ rmd160_machash(&mc, p, sz);
+ rmd160_macdone(&mc, b);
+ if (memcmp(b, k->u.k.k + RMD160_HASHSZ, RMD160_HASHSZ) != 0) {
passphrase_cancel(tag);
passphrase_cancel(tag);
- goto fail
_1
;
+ goto fail;
}
}
+ BURN(mk);
+ BURN(mc);
}
/* --- Decode the key data into the destination buffer --- */
}
/* --- Decode the key data into the destination buffer --- */
@@
-194,8
+231,8
@@
int key_punlock(const char *tag, key_data *k, key_data *kt)
key_destroy(k);
passphrase_cancel(tag);
}
key_destroy(k);
passphrase_cancel(tag);
}
- if (key_decode(p
+ 4, sz - 4
, kt))
- goto fail
_1
;
+ if (key_decode(p
, sz
, kt))
+ goto fail;
/* --- Done --- */
/* --- Done --- */
@@
-204,9
+241,9
@@
int key_punlock(const char *tag, key_data *k, key_data *kt)
/* --- Tidy up if things went wrong --- */
/* --- Tidy up if things went wrong --- */
-fail_1:
+fail:
+ BURN(b);
free(p);
free(p);
-fail_0:
return (-1);
}
return (-1);
}