~ubuntu-branches/ubuntu/lucid/openssh/lucid

« back to all changes in this revision

Viewing changes to mac.c

  • Committer: Bazaar Package Importer
  • Author(s): Colin Watson
  • Date: 2008-09-30 23:09:58 UTC
  • mfrom: (1.13.3 upstream) (29 hardy)
  • mto: This revision was merged to the branch mainline in revision 43.
  • Revision ID: james.westby@ubuntu.com-20080930230958-o6vsgn8c4mm959s0
Tags: 1:5.1p1-3
* Remove unnecessary ssh-vulnkey output in non-verbose mode when no
  compromised or unknown keys were found (closes: #496495).
* Configure with --disable-strip; dh_strip will deal with stripping
  binaries and will honour DEB_BUILD_OPTIONS (thanks, Bernhard R. Link;
  closes: #498681).
* Fix handling of zero-length server banners (thanks, Tomas Mraz; closes:
  #497026).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* $OpenBSD: mac.c,v 1.12 2006/08/03 03:34:42 deraadt Exp $ */
 
1
/* $OpenBSD: mac.c,v 1.15 2008/06/13 00:51:47 dtucker Exp $ */
2
2
/*
3
3
 * Copyright (c) 2001 Markus Friedl.  All rights reserved.
4
4
 *
42
42
#include "mac.h"
43
43
#include "misc.h"
44
44
 
 
45
#include "umac.h"
 
46
 
 
47
#define SSH_EVP         1       /* OpenSSL EVP-based MAC */
 
48
#define SSH_UMAC        2       /* UMAC (not integrated with OpenSSL) */
 
49
 
45
50
struct {
46
51
        char            *name;
 
52
        int             type;
47
53
        const EVP_MD *  (*mdfunc)(void);
48
54
        int             truncatebits;   /* truncate digest if != 0 */
 
55
        int             key_len;        /* just for UMAC */
 
56
        int             len;            /* just for UMAC */
49
57
} macs[] = {
50
 
        { "hmac-sha1",                  EVP_sha1, 0, },
51
 
        { "hmac-sha1-96",               EVP_sha1, 96 },
52
 
        { "hmac-md5",                   EVP_md5, 0 },
53
 
        { "hmac-md5-96",                EVP_md5, 96 },
54
 
        { "hmac-ripemd160",             EVP_ripemd160, 0 },
55
 
        { "hmac-ripemd160@openssh.com", EVP_ripemd160, 0 },
56
 
        { NULL,                         NULL, 0 }
 
58
        { "hmac-sha1",                  SSH_EVP, EVP_sha1, 0, -1, -1 },
 
59
        { "hmac-sha1-96",               SSH_EVP, EVP_sha1, 96, -1, -1 },
 
60
        { "hmac-md5",                   SSH_EVP, EVP_md5, 0, -1, -1 },
 
61
        { "hmac-md5-96",                SSH_EVP, EVP_md5, 96, -1, -1 },
 
62
        { "hmac-ripemd160",             SSH_EVP, EVP_ripemd160, 0, -1, -1 },
 
63
        { "hmac-ripemd160@openssh.com", SSH_EVP, EVP_ripemd160, 0, -1, -1 },
 
64
        { "umac-64@openssh.com",        SSH_UMAC, NULL, 0, 128, 64 },
 
65
        { NULL,                         0, NULL, 0, -1, -1 }
57
66
};
58
67
 
 
68
static void
 
69
mac_setup_by_id(Mac *mac, int which)
 
70
{
 
71
        int evp_len;
 
72
        mac->type = macs[which].type;
 
73
        if (mac->type == SSH_EVP) {
 
74
                mac->evp_md = (*macs[which].mdfunc)();
 
75
                if ((evp_len = EVP_MD_size(mac->evp_md)) <= 0)
 
76
                        fatal("mac %s len %d", mac->name, evp_len);
 
77
                mac->key_len = mac->mac_len = (u_int)evp_len;
 
78
        } else {
 
79
                mac->mac_len = macs[which].len / 8;
 
80
                mac->key_len = macs[which].key_len / 8;
 
81
                mac->umac_ctx = NULL;
 
82
        }
 
83
        if (macs[which].truncatebits != 0)
 
84
                mac->mac_len = macs[which].truncatebits / 8;
 
85
}
 
86
 
59
87
int
60
 
mac_init(Mac *mac, char *name)
 
88
mac_setup(Mac *mac, char *name)
61
89
{
62
 
        int i, evp_len;
 
90
        int i;
63
91
 
64
92
        for (i = 0; macs[i].name; i++) {
65
93
                if (strcmp(name, macs[i].name) == 0) {
66
 
                        if (mac != NULL) {
67
 
                                mac->md = (*macs[i].mdfunc)();
68
 
                                if ((evp_len = EVP_MD_size(mac->md)) <= 0)
69
 
                                        fatal("mac %s len %d", name, evp_len);
70
 
                                mac->key_len = mac->mac_len = (u_int)evp_len;
71
 
                                if (macs[i].truncatebits != 0)
72
 
                                        mac->mac_len = macs[i].truncatebits/8;
73
 
                        }
74
 
                        debug2("mac_init: found %s", name);
 
94
                        if (mac != NULL)
 
95
                                mac_setup_by_id(mac, i);
 
96
                        debug2("mac_setup: found %s", name);
75
97
                        return (0);
76
98
                }
77
99
        }
78
 
        debug2("mac_init: unknown %s", name);
 
100
        debug2("mac_setup: unknown %s", name);
79
101
        return (-1);
80
102
}
81
103
 
 
104
int
 
105
mac_init(Mac *mac)
 
106
{
 
107
        if (mac->key == NULL)
 
108
                fatal("mac_init: no key");
 
109
        switch (mac->type) {
 
110
        case SSH_EVP:
 
111
                if (mac->evp_md == NULL)
 
112
                        return -1;
 
113
                HMAC_Init(&mac->evp_ctx, mac->key, mac->key_len, mac->evp_md);
 
114
                return 0;
 
115
        case SSH_UMAC:
 
116
                mac->umac_ctx = umac_new(mac->key);
 
117
                return 0;
 
118
        default:
 
119
                return -1;
 
120
        }
 
121
}
 
122
 
82
123
u_char *
83
124
mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
84
125
{
85
 
        HMAC_CTX c;
86
126
        static u_char m[EVP_MAX_MD_SIZE];
87
 
        u_char b[4];
 
127
        u_char b[4], nonce[8];
88
128
 
89
 
        if (mac->key == NULL)
90
 
                fatal("mac_compute: no key");
91
129
        if (mac->mac_len > sizeof(m))
92
 
                fatal("mac_compute: mac too long");
93
 
        HMAC_Init(&c, mac->key, mac->key_len, mac->md);
94
 
        put_u32(b, seqno);
95
 
        HMAC_Update(&c, b, sizeof(b));
96
 
        HMAC_Update(&c, data, datalen);
97
 
        HMAC_Final(&c, m, NULL);
98
 
        HMAC_cleanup(&c);
 
130
                fatal("mac_compute: mac too long %u %lu",
 
131
                    mac->mac_len, (u_long)sizeof(m));
 
132
 
 
133
        switch (mac->type) {
 
134
        case SSH_EVP:
 
135
                put_u32(b, seqno);
 
136
                /* reset HMAC context */
 
137
                HMAC_Init(&mac->evp_ctx, NULL, 0, NULL);
 
138
                HMAC_Update(&mac->evp_ctx, b, sizeof(b));
 
139
                HMAC_Update(&mac->evp_ctx, data, datalen);
 
140
                HMAC_Final(&mac->evp_ctx, m, NULL);
 
141
                break;
 
142
        case SSH_UMAC:
 
143
                put_u64(nonce, seqno);
 
144
                umac_update(mac->umac_ctx, data, datalen);
 
145
                umac_final(mac->umac_ctx, m, nonce);
 
146
                break;
 
147
        default:
 
148
                fatal("mac_compute: unknown MAC type");
 
149
        }
99
150
        return (m);
100
151
}
101
152
 
 
153
void
 
154
mac_clear(Mac *mac)
 
155
{
 
156
        if (mac->type == SSH_UMAC) {
 
157
                if (mac->umac_ctx != NULL)
 
158
                        umac_delete(mac->umac_ctx);
 
159
        } else if (mac->evp_md != NULL)
 
160
                HMAC_cleanup(&mac->evp_ctx);
 
161
        mac->evp_md = NULL;
 
162
        mac->umac_ctx = NULL;
 
163
}
 
164
 
102
165
/* XXX copied from ciphers_valid */
103
166
#define MAC_SEP ","
104
167
int
111
174
        maclist = cp = xstrdup(names);
112
175
        for ((p = strsep(&cp, MAC_SEP)); p && *p != '\0';
113
176
            (p = strsep(&cp, MAC_SEP))) {
114
 
                if (mac_init(NULL, p) < 0) {
 
177
                if (mac_setup(NULL, p) < 0) {
115
178
                        debug("bad mac %s [%s]", p, names);
116
179
                        xfree(maclist);
117
180
                        return (0);