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

Annotation of src/usr.bin/ssh/digest-libc.c, Revision 1.2

1.2     ! djm         1: /* $OpenBSD: digest-libc.c,v 1.1 2014/01/28 20:13:46 markus Exp $ */
1.1       markus      2: /*
                      3:  * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
                      4:  * Copyright (c) 2014 Markus Friedl.  All rights reserved.
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  */
                     18:
                     19: #include <sys/types.h>
                     20: #include <limits.h>
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23:
                     24: #include <md5.h>
                     25: #include <rmd160.h>
                     26: #include <sha1.h>
                     27: #include <sha2.h>
                     28:
                     29: #include "buffer.h"
                     30: #include "digest.h"
                     31:
                     32: typedef void md_init_fn(void *mdctx);
                     33: typedef void md_update_fn(void *mdctx, const u_int8_t *m, size_t mlen);
                     34: typedef void md_final_fn(u_int8_t[], void *mdctx);
                     35:
                     36: struct ssh_digest_ctx {
                     37:        int alg;
                     38:        void *mdctx;
                     39: };
                     40:
                     41: struct ssh_digest {
                     42:        int id;
                     43:        const char *name;
                     44:        size_t block_len;
                     45:        size_t digest_len;
                     46:        size_t ctx_len;
                     47:        md_init_fn *md_init;
                     48:        md_update_fn *md_update;
                     49:        md_final_fn *md_final;
                     50: };
                     51:
                     52: /* NB. Indexed directly by algorithm number */
                     53: const struct ssh_digest digests[SSH_DIGEST_MAX] = {
                     54:        {
                     55:                SSH_DIGEST_MD5,
                     56:                "MD5",
                     57:                MD5_BLOCK_LENGTH,
                     58:                MD5_DIGEST_LENGTH,
                     59:                sizeof(MD5_CTX),
                     60:                (md_init_fn *) MD5Init,
                     61:                (md_update_fn *) MD5Update,
                     62:                (md_final_fn *) MD5Final
                     63:        },
                     64:        {
                     65:                SSH_DIGEST_RIPEMD160,
                     66:                "RIPEMD160",
                     67:                RMD160_BLOCK_LENGTH,
                     68:                RMD160_DIGEST_LENGTH,
                     69:                sizeof(RMD160_CTX),
                     70:                (md_init_fn *) RMD160Init,
                     71:                (md_update_fn *) RMD160Update,
                     72:                (md_final_fn *) RMD160Final
                     73:        },
                     74:        {
                     75:                SSH_DIGEST_SHA1,
                     76:                "SHA1",
                     77:                SHA1_BLOCK_LENGTH,
                     78:                SHA1_DIGEST_LENGTH,
                     79:                sizeof(SHA1_CTX),
                     80:                (md_init_fn *) SHA1Init,
                     81:                (md_update_fn *) SHA1Update,
                     82:                (md_final_fn *) SHA1Final
                     83:        },
                     84:        {
                     85:                SSH_DIGEST_SHA256,
                     86:                "SHA256",
                     87:                SHA256_BLOCK_LENGTH,
                     88:                SHA256_DIGEST_LENGTH,
                     89:                sizeof(SHA2_CTX),
                     90:                (md_init_fn *) SHA256Init,
                     91:                (md_update_fn *) SHA256Update,
                     92:                (md_final_fn *) SHA256Final
                     93:        },
                     94:        {
                     95:                SSH_DIGEST_SHA384,
                     96:                "SHA384",
                     97:                SHA384_BLOCK_LENGTH,
                     98:                SHA384_DIGEST_LENGTH,
                     99:                sizeof(SHA2_CTX),
                    100:                (md_init_fn *) SHA384Init,
                    101:                (md_update_fn *) SHA384Update,
                    102:                (md_final_fn *) SHA384Final
                    103:        },
                    104:        {
                    105:                SSH_DIGEST_SHA512,
                    106:                "SHA512",
                    107:                SHA512_BLOCK_LENGTH,
                    108:                SHA512_DIGEST_LENGTH,
                    109:                sizeof(SHA2_CTX),
                    110:                (md_init_fn *) SHA512Init,
                    111:                (md_update_fn *) SHA512Update,
                    112:                (md_final_fn *) SHA512Final
                    113:        }
                    114: };
                    115:
                    116: static const struct ssh_digest *
                    117: ssh_digest_by_alg(int alg)
                    118: {
                    119:        if (alg < 0 || alg >= SSH_DIGEST_MAX)
                    120:                return NULL;
                    121:        if (digests[alg].id != alg) /* sanity */
                    122:                return NULL;
                    123:        return &(digests[alg]);
                    124: }
                    125:
                    126: size_t
                    127: ssh_digest_bytes(int alg)
                    128: {
                    129:        const struct ssh_digest *digest = ssh_digest_by_alg(alg);
                    130:
                    131:        return digest == NULL ? 0 : digest->digest_len;
                    132: }
                    133:
                    134: size_t
                    135: ssh_digest_blocksize(struct ssh_digest_ctx *ctx)
                    136: {
                    137:        const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
                    138:
                    139:        return digest == NULL ? 0 : digest->block_len;
                    140: }
                    141:
                    142: struct ssh_digest_ctx *
                    143: ssh_digest_start(int alg)
                    144: {
                    145:        const struct ssh_digest *digest = ssh_digest_by_alg(alg);
                    146:        struct ssh_digest_ctx *ret;
                    147:
                    148:        if (digest == NULL || (ret = calloc(1, sizeof(ret))) == NULL)
                    149:                return NULL;
                    150:        if ((ret->mdctx = calloc(1, digest->ctx_len)) == NULL) {
                    151:                free(ret);
                    152:                return NULL;
                    153:        }
                    154:        ret->alg = alg;
                    155:        digest->md_init(ret->mdctx);
                    156:        return ret;
                    157: }
                    158:
                    159: int
                    160: ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
                    161: {
                    162:        const struct ssh_digest *digest = ssh_digest_by_alg(from->alg);
                    163:
                    164:        if (digest == NULL || from->alg != to->alg)
                    165:                return -1;
                    166:        memcpy(to->mdctx, from->mdctx, digest->ctx_len);
                    167:        return 0;
                    168: }
                    169:
                    170: int
                    171: ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
                    172: {
                    173:        const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
                    174:
                    175:        if (digest == NULL)
                    176:                return -1;
                    177:        digest->md_update(ctx->mdctx, m, mlen);
                    178:        return 0;
                    179: }
                    180:
                    181: int
                    182: ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b)
                    183: {
                    184:        return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b));
                    185: }
                    186:
                    187: int
                    188: ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
                    189: {
                    190:        const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
                    191:
                    192:        if (digest == NULL)
                    193:                return -1;
                    194:        if (dlen > UINT_MAX)
                    195:                return -1;
                    196:        if (dlen < digest->digest_len) /* No truncation allowed */
                    197:                return -1;
                    198:        digest->md_final(d, ctx->mdctx);
                    199:        return 0;
                    200: }
                    201:
                    202: void
                    203: ssh_digest_free(struct ssh_digest_ctx *ctx)
                    204: {
                    205:        const struct ssh_digest *digest;
                    206:
                    207:        if (ctx != NULL) {
                    208:                digest = ssh_digest_by_alg(ctx->alg);
                    209:                if (digest) {
1.2     ! djm       210:                        explicit_bzero(ctx->mdctx, digest->ctx_len);
1.1       markus    211:                        free(ctx->mdctx);
1.2     ! djm       212:                        explicit_bzero(ctx, sizeof(*ctx));
1.1       markus    213:                        free(ctx);
                    214:                }
                    215:        }
                    216: }
                    217:
                    218: int
                    219: ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
                    220: {
                    221:        struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
                    222:
                    223:        if (ctx == NULL)
                    224:                return -1;
                    225:        if (ssh_digest_update(ctx, m, mlen) != 0 ||
                    226:            ssh_digest_final(ctx, d, dlen) != 0)
                    227:                return -1;
                    228:        ssh_digest_free(ctx);
                    229:        return 0;
                    230: }
                    231:
                    232: int
                    233: ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen)
                    234: {
                    235:        return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen);
                    236: }