[BACK]Return to mac.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/mac.c between version 1.30 and 1.31

version 1.30, 2014/04/30 19:07:48 version 1.31, 2015/01/13 19:31:40
Line 25 
Line 25 
   
 #include <sys/types.h>  #include <sys/types.h>
   
 #include <openssl/hmac.h>  
   
 #include <string.h>  #include <string.h>
 #include <signal.h>  #include <stdio.h>
   
 #include "xmalloc.h"  
 #include "log.h"  
 #include "cipher.h"  
 #include "buffer.h"  
 #include "key.h"  
 #include "kex.h"  
 #include "mac.h"  
 #include "misc.h"  
   
 #include "digest.h"  #include "digest.h"
 #include "hmac.h"  #include "hmac.h"
 #include "umac.h"  #include "umac.h"
   #include "mac.h"
   #include "misc.h"
   #include "ssherr.h"
   #include "sshbuf.h"
   
 #define SSH_DIGEST      1       /* SSH_DIGEST_XXX */  #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) */
Line 88 
Line 81 
 char *  char *
 mac_alg_list(char sep)  mac_alg_list(char sep)
 {  {
         char *ret = NULL;          char *ret = NULL, *tmp;
         size_t nlen, rlen = 0;          size_t nlen, rlen = 0;
         const struct macalg *m;          const struct macalg *m;
   
Line 96 
Line 89 
                 if (ret != NULL)                  if (ret != NULL)
                         ret[rlen++] = sep;                          ret[rlen++] = sep;
                 nlen = strlen(m->name);                  nlen = strlen(m->name);
                 ret = xrealloc(ret, 1, rlen + nlen + 2);                  if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
                           free(ret);
                           return NULL;
                   }
                   ret = tmp;
                 memcpy(ret + rlen, m->name, nlen + 1);                  memcpy(ret + rlen, m->name, nlen + 1);
                 rlen += nlen;                  rlen += nlen;
         }          }
         return ret;          return ret;
 }  }
   
 static void  static int
 mac_setup_by_alg(Mac *mac, const struct macalg *macalg)  mac_setup_by_alg(struct sshmac *mac, const struct macalg *macalg)
 {  {
         mac->type = macalg->type;          mac->type = macalg->type;
         if (mac->type == SSH_DIGEST) {          if (mac->type == SSH_DIGEST) {
                 if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)                  if ((mac->hmac_ctx = ssh_hmac_start(macalg->alg)) == NULL)
                         fatal("ssh_hmac_start(alg=%d) failed", macalg->alg);                          return SSH_ERR_ALLOC_FAIL;
                 mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);                  mac->key_len = mac->mac_len = ssh_hmac_bytes(macalg->alg);
         } else {          } else {
                 mac->mac_len = macalg->len / 8;                  mac->mac_len = macalg->len / 8;
Line 119 
Line 116 
         if (macalg->truncatebits != 0)          if (macalg->truncatebits != 0)
                 mac->mac_len = macalg->truncatebits / 8;                  mac->mac_len = macalg->truncatebits / 8;
         mac->etm = macalg->etm;          mac->etm = macalg->etm;
           return 0;
 }  }
   
 int  int
 mac_setup(Mac *mac, char *name)  mac_setup(struct sshmac *mac, char *name)
 {  {
         const struct macalg *m;          const struct macalg *m;
   
         for (m = macs; m->name != NULL; m++) {          for (m = macs; m->name != NULL; m++) {
                 if (strcmp(name, m->name) != 0)                  if (strcmp(name, m->name) != 0)
                         continue;                          continue;
                 if (mac != NULL) {                  if (mac != NULL)
                         mac_setup_by_alg(mac, m);                          return mac_setup_by_alg(mac, m);
                         debug2("mac_setup: setup %s", name);                  return 0;
                 }  
                 return (0);  
         }          }
         debug2("mac_setup: unknown %s", name);          return SSH_ERR_INVALID_ARGUMENT;
         return (-1);  
 }  }
   
 int  int
 mac_init(Mac *mac)  mac_init(struct sshmac *mac)
 {  {
         if (mac->key == NULL)          if (mac->key == NULL)
                 fatal("%s: no key", __func__);                  return SSH_ERR_INVALID_ARGUMENT;
         switch (mac->type) {          switch (mac->type) {
         case SSH_DIGEST:          case SSH_DIGEST:
                 if (mac->hmac_ctx == NULL ||                  if (mac->hmac_ctx == NULL ||
                     ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)                      ssh_hmac_init(mac->hmac_ctx, mac->key, mac->key_len) < 0)
                         return -1;                          return SSH_ERR_INVALID_ARGUMENT;
                 return 0;                  return 0;
         case SSH_UMAC:          case SSH_UMAC:
                 mac->umac_ctx = umac_new(mac->key);                  if ((mac->umac_ctx = umac_new(mac->key)) == NULL)
                           return SSH_ERR_ALLOC_FAIL;
                 return 0;                  return 0;
         case SSH_UMAC128:          case SSH_UMAC128:
                 mac->umac_ctx = umac128_new(mac->key);                  mac->umac_ctx = umac128_new(mac->key);
                 return 0;                  return 0;
         default:          default:
                 return -1;                  return SSH_ERR_INVALID_ARGUMENT;
         }          }
 }  }
   
 u_char *  int
 mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)  mac_compute(struct sshmac *mac, u_int32_t seqno, const u_char *data, int datalen,
       u_char *digest, size_t dlen)
 {  {
         static union {          static union {
                 u_char m[EVP_MAX_MD_SIZE];                  u_char m[SSH_DIGEST_MAX_LENGTH];
                 u_int64_t for_align;                  u_int64_t for_align;
         } u;          } u;
         u_char b[4];          u_char b[4];
         u_char nonce[8];          u_char nonce[8];
   
         if (mac->mac_len > sizeof(u))          if (mac->mac_len > sizeof(u))
                 fatal("mac_compute: mac too long %u %zu",                  return SSH_ERR_INTERNAL_ERROR;
                     mac->mac_len, sizeof(u));  
   
         switch (mac->type) {          switch (mac->type) {
         case SSH_DIGEST:          case SSH_DIGEST:
Line 183 
Line 179 
                     ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 ||                      ssh_hmac_update(mac->hmac_ctx, b, sizeof(b)) < 0 ||
                     ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 ||                      ssh_hmac_update(mac->hmac_ctx, data, datalen) < 0 ||
                     ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)                      ssh_hmac_final(mac->hmac_ctx, u.m, sizeof(u.m)) < 0)
                         fatal("ssh_hmac failed");                          return SSH_ERR_LIBCRYPTO_ERROR;
                 break;                  break;
         case SSH_UMAC:          case SSH_UMAC:
                 put_u64(nonce, seqno);                  POKE_U64(nonce, seqno);
                 umac_update(mac->umac_ctx, data, datalen);                  umac_update(mac->umac_ctx, data, datalen);
                 umac_final(mac->umac_ctx, u.m, nonce);                  umac_final(mac->umac_ctx, u.m, nonce);
                 break;                  break;
Line 196 
Line 192 
                 umac128_final(mac->umac_ctx, u.m, nonce);                  umac128_final(mac->umac_ctx, u.m, nonce);
                 break;                  break;
         default:          default:
                 fatal("mac_compute: unknown MAC type");                  return SSH_ERR_INVALID_ARGUMENT;
         }          }
         return (u.m);          if (digest != NULL) {
                   if (dlen > mac->mac_len)
                           dlen = mac->mac_len;
                   memcpy(digest, u.m, dlen);
           }
           return 0;
 }  }
   
 void  void
 mac_clear(Mac *mac)  mac_clear(struct sshmac *mac)
 {  {
         if (mac->type == SSH_UMAC) {          if (mac->type == SSH_UMAC) {
                 if (mac->umac_ctx != NULL)                  if (mac->umac_ctx != NULL)
Line 224 
Line 225 
         char *maclist, *cp, *p;          char *maclist, *cp, *p;
   
         if (names == NULL || strcmp(names, "") == 0)          if (names == NULL || strcmp(names, "") == 0)
                 return (0);                  return 0;
         maclist = cp = xstrdup(names);          if ((maclist = cp = strdup(names)) == NULL)
                   return 0;
         for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';          for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
             (p = strsep(&cp, MAC_SEP))) {              (p = strsep(&cp, MAC_SEP))) {
                 if (mac_setup(NULL, p) < 0) {                  if (mac_setup(NULL, p) < 0) {
                         debug("bad mac %s [%s]", p, names);  
                         free(maclist);                          free(maclist);
                         return (0);                          return 0;
                 }                  }
         }          }
         debug3("macs ok: [%s]", names);  
         free(maclist);          free(maclist);
         return (1);          return 1;
 }  }

Legend:
Removed from v.1.30  
changed lines
  Added in v.1.31