version 1.26, 2014/01/04 17:50:55 |
version 1.27, 2014/01/27 18:58:14 |
|
|
#include "mac.h" |
#include "mac.h" |
#include "misc.h" |
#include "misc.h" |
|
|
|
#include "digest.h" |
|
#include "hmac.h" |
#include "umac.h" |
#include "umac.h" |
|
|
#define SSH_EVP 1 /* OpenSSL EVP-based MAC */ |
#define SSH_DIGEST 1 /* SSH_DIGEST_XXX */ |
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ |
#define SSH_UMAC 2 /* UMAC (not integrated with OpenSSL) */ |
#define SSH_UMAC128 3 |
#define SSH_UMAC128 3 |
|
|
struct macalg { |
struct macalg { |
char *name; |
char *name; |
int type; |
int type; |
const EVP_MD * (*mdfunc)(void); |
int alg; |
int truncatebits; /* truncate digest if != 0 */ |
int truncatebits; /* truncate digest if != 0 */ |
int key_len; /* just for UMAC */ |
int key_len; /* just for UMAC */ |
int len; /* just for UMAC */ |
int len; /* just for UMAC */ |
|
|
|
|
static const struct macalg macs[] = { |
static const struct macalg macs[] = { |
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */ |
/* Encrypt-and-MAC (encrypt-and-authenticate) variants */ |
{ "hmac-sha1", SSH_EVP, EVP_sha1, 0, 0, 0, 0 }, |
{ "hmac-sha1", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 0 }, |
{ "hmac-sha1-96", SSH_EVP, EVP_sha1, 96, 0, 0, 0 }, |
{ "hmac-sha1-96", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 0 }, |
{ "hmac-sha2-256", SSH_EVP, EVP_sha256, 0, 0, 0, 0 }, |
{ "hmac-sha2-256", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 0 }, |
{ "hmac-sha2-512", SSH_EVP, EVP_sha512, 0, 0, 0, 0 }, |
{ "hmac-sha2-512", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 0 }, |
{ "hmac-md5", SSH_EVP, EVP_md5, 0, 0, 0, 0 }, |
{ "hmac-md5", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 0 }, |
{ "hmac-md5-96", SSH_EVP, EVP_md5, 96, 0, 0, 0 }, |
{ "hmac-md5-96", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 0 }, |
{ "hmac-ripemd160", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 }, |
{ "hmac-ripemd160", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 }, |
{ "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 0 }, |
{ "hmac-ripemd160@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 0 }, |
{ "umac-64@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 0 }, |
{ "umac-64@openssh.com", SSH_UMAC, 0, 0, 128, 64, 0 }, |
{ "umac-128@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 0 }, |
{ "umac-128@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 0 }, |
|
|
/* Encrypt-then-MAC variants */ |
/* Encrypt-then-MAC variants */ |
{ "hmac-sha1-etm@openssh.com", SSH_EVP, EVP_sha1, 0, 0, 0, 1 }, |
{ "hmac-sha1-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 0, 0, 0, 1 }, |
{ "hmac-sha1-96-etm@openssh.com", SSH_EVP, EVP_sha1, 96, 0, 0, 1 }, |
{ "hmac-sha1-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA1, 96, 0, 0, 1 }, |
{ "hmac-sha2-256-etm@openssh.com", SSH_EVP, EVP_sha256, 0, 0, 0, 1 }, |
{ "hmac-sha2-256-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA256, 0, 0, 0, 1 }, |
{ "hmac-sha2-512-etm@openssh.com", SSH_EVP, EVP_sha512, 0, 0, 0, 1 }, |
{ "hmac-sha2-512-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_SHA512, 0, 0, 0, 1 }, |
{ "hmac-md5-etm@openssh.com", SSH_EVP, EVP_md5, 0, 0, 0, 1 }, |
{ "hmac-md5-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 0, 0, 0, 1 }, |
{ "hmac-md5-96-etm@openssh.com", SSH_EVP, EVP_md5, 96, 0, 0, 1 }, |
{ "hmac-md5-96-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_MD5, 96, 0, 0, 1 }, |
{ "hmac-ripemd160-etm@openssh.com", SSH_EVP, EVP_ripemd160, 0, 0, 0, 1 }, |
{ "hmac-ripemd160-etm@openssh.com", SSH_DIGEST, SSH_DIGEST_RIPEMD160, 0, 0, 0, 1 }, |
{ "umac-64-etm@openssh.com", SSH_UMAC, NULL, 0, 128, 64, 1 }, |
{ "umac-64-etm@openssh.com", SSH_UMAC, 0, 0, 128, 64, 1 }, |
{ "umac-128-etm@openssh.com", SSH_UMAC128, NULL, 0, 128, 128, 1 }, |
{ "umac-128-etm@openssh.com", SSH_UMAC128, 0, 0, 128, 128, 1 }, |
|
|
{ NULL, 0, NULL, 0, 0, 0, 0 } |
{ NULL, 0, 0, 0, 0, 0, 0 } |
}; |
}; |
|
|
/* Returns a list of supported MACs separated by the specified char. */ |
/* Returns a list of supported MACs separated by the specified char. */ |
|
|
static void |
static void |
mac_setup_by_alg(Mac *mac, const struct macalg *macalg) |
mac_setup_by_alg(Mac *mac, const struct macalg *macalg) |
{ |
{ |
int evp_len; |
|
|
|
mac->type = macalg->type; |
mac->type = macalg->type; |
if (mac->type == SSH_EVP) { |
if (mac->type == SSH_DIGEST) { |
mac->evp_md = macalg->mdfunc(); |
if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL) |
if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0) |
fatal("ssh_hmac_start(alg=%d) failed", macalg->alg); |
fatal("mac %s len %d", mac->name, evp_len); |
mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg); |
mac->key_len = mac->mac_len = (u_int)evp_len; |
|
} else { |
} else { |
mac->mac_len = macalg->len / 8; |
mac->mac_len = macalg->len / 8; |
mac->key_len = macalg->key_len / 8; |
mac->key_len = macalg->key_len / 8; |
|
|
if (mac->key == NULL) |
if (mac->key == NULL) |
fatal("mac_init: no key"); |
fatal("mac_init: no key"); |
switch (mac->type) { |
switch (mac->type) { |
case SSH_EVP: |
case SSH_DIGEST: |
if (mac->evp_md == NULL) |
if (mac->hmac_ctx == NULL || |
|
ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0) |
return -1; |
return -1; |
HMAC_CTX_init(&mac->evp_ctx); |
|
HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md); |
|
return 0; |
return 0; |
case SSH_UMAC: |
case SSH_UMAC: |
mac->umac_ctx = umac_new(mac->key); |
mac->umac_ctx = umac_new(mac->key); |
|
|
mac->mac_len, sizeof(u)); |
mac->mac_len, sizeof(u)); |
|
|
switch (mac->type) { |
switch (mac->type) { |
case SSH_EVP: |
case SSH_DIGEST: |
put_u32(b, seqno); |
put_u32(b, seqno); |
/* reset HMAC context */ |
/* reset HMAC context */ |
HMAC_Init(&mac->evp_ctx, NULL, 0, NULL); |
if (ssh_hmac_init(mac->hmac_ctx, NULL, 0) < 0 || |
HMAC_Update(&mac->evp_ctx, b, sizeof(b)); |
ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 || |
HMAC_Update(&mac->evp_ctx, data, datalen); |
ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 || |
HMAC_Final(&mac->evp_ctx, u.m, NULL); |
ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0) |
|
fatal("ssh_hmac failed"); |
break; |
break; |
case SSH_UMAC: |
case SSH_UMAC: |
put_u64(nonce, seqno); |
put_u64(nonce, seqno); |
|
|
} else if (mac->type == SSH_UMAC128) { |
} else if (mac->type == SSH_UMAC128) { |
if (mac->umac_ctx != NULL) |
if (mac->umac_ctx != NULL) |
umac128_delete(mac->umac_ctx); |
umac128_delete(mac->umac_ctx); |
} else if (mac->evp_md != NULL) |
} else if (mac->hmac_ctx != NULL) |
HMAC_cleanup(&mac->evp_ctx); |
ssh_hmac_free(mac->hmac_ctx); |
mac->evp_md = NULL; |
mac->hmac_ctx = NULL; |
mac->umac_ctx = NULL; |
mac->umac_ctx = NULL; |
} |
} |
|
|