radius_msgauth.c revision 1.5
1/* $OpenBSD: radius_msgauth.c,v 1.5 2024/08/14 04:50:31 yasuoka Exp $ */ 2 3/*- 4 * Copyright (c) 2009 Internet Initiative Japan Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE"AUTHOR" AND CONTRIBUTORS AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29#include <sys/types.h> 30#include <sys/socket.h> 31#include <netinet/in.h> 32 33#include <stdbool.h> 34#include <stdio.h> 35#include <stdlib.h> 36#include <string.h> 37 38#include <openssl/hmac.h> 39 40#include "radius.h" 41 42#include "radius_local.h" 43 44static int 45radius_calc_message_authenticator(RADIUS_PACKET * packet, const char *secret, 46 void *ma) 47{ 48 const RADIUS_ATTRIBUTE *attr; 49 const RADIUS_ATTRIBUTE *end; 50 u_char zero16[16]; 51 HMAC_CTX *ctx; 52 int mdlen; 53 int ret = -1; 54 55 memset(zero16, 0, sizeof(zero16)); 56 57 if ((ctx = HMAC_CTX_new()) == NULL) 58 goto err; 59 60 if (!HMAC_Init_ex(ctx, secret, strlen(secret), EVP_md5(), NULL)) 61 goto err; 62 63 /* 64 * Traverse the radius packet. 65 */ 66 if (packet->request != NULL) { 67 if (!HMAC_Update(ctx, (const u_char *)packet->pdata, 4)) 68 goto err; 69 if (!HMAC_Update(ctx, (unsigned char *)packet->request->pdata 70 ->authenticator, 16)) 71 goto err; 72 } else { 73 if (!HMAC_Update(ctx, (const u_char *)packet->pdata, 74 sizeof(RADIUS_PACKET_DATA))) 75 goto err; 76 } 77 78 attr = ATTRS_BEGIN(packet->pdata); 79 end = ATTRS_END(packet->pdata); 80 81 for (; attr < end; ATTRS_ADVANCE(attr)) { 82 if (attr->type == RADIUS_TYPE_MESSAGE_AUTHENTICATOR) { 83 if (!HMAC_Update(ctx, (u_char *)attr, 2)) 84 goto err; 85 if (!HMAC_Update(ctx, (u_char *)zero16, sizeof(zero16))) 86 goto err; 87 } else { 88 if (!HMAC_Update(ctx, (u_char *)attr, 89 (int)attr->length)) 90 goto err; 91 } 92 } 93 94 if (!HMAC_Final(ctx, (u_char *)ma, &mdlen)) 95 goto err; 96 97 ret = 0; 98 99 err: 100 HMAC_CTX_free(ctx); 101 102 return (ret); 103} 104 105int 106radius_put_message_authenticator(RADIUS_PACKET * packet, const char *secret) 107{ 108 u_char ma[16]; 109 110 /* 111 * It is not required to initialize ma 112 * because content of Message-Authenticator attribute is assumed zero 113 * during calculation. 114 */ 115 if (radius_unshift_raw_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR, 116 ma, sizeof(ma)) != 0) 117 return (-1); 118 119 return (radius_set_message_authenticator(packet, secret)); 120} 121 122int 123radius_set_message_authenticator(RADIUS_PACKET * packet, const char *secret) 124{ 125 u_char ma[16]; 126 127 if (radius_calc_message_authenticator(packet, secret, ma) != 0) 128 return (-1); 129 130 return (radius_set_raw_attr(packet, RADIUS_TYPE_MESSAGE_AUTHENTICATOR, 131 ma, sizeof(ma))); 132} 133 134int 135radius_check_message_authenticator(RADIUS_PACKET * packet, const char *secret) 136{ 137 int rval; 138 size_t len; 139 u_char ma0[16], ma1[16]; 140 141 if (radius_calc_message_authenticator(packet, secret, ma0) != 0) 142 return (-1); 143 144 len = sizeof(ma1); 145 if ((rval = radius_get_raw_attr(packet, 146 RADIUS_TYPE_MESSAGE_AUTHENTICATOR, ma1, &len)) != 0) 147 return (rval); 148 149 if (len != sizeof(ma1)) 150 return (-1); 151 152 return (timingsafe_bcmp(ma0, ma1, sizeof(ma1))); 153} 154