|
gsasl
1.8.0
|
00001 /* session.c --- Data integrity/privacy protection of DIGEST-MD5. 00002 * Copyright (C) 2002-2012 Simon Josefsson 00003 * 00004 * This file is part of GNU SASL Library. 00005 * 00006 * GNU SASL Library is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public License 00008 * as published by the Free Software Foundation; either version 2.1 of 00009 * the License, or (at your option) any later version. 00010 * 00011 * GNU SASL Library is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with GNU SASL Library; if not, write to the Free 00018 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 * Boston, MA 02110-1301, USA. 00020 * 00021 */ 00022 00023 #ifdef HAVE_CONFIG_H 00024 #include "config.h" 00025 #endif 00026 00027 /* Get specification. */ 00028 #include "session.h" 00029 00030 /* Get malloc, free. */ 00031 #include <stdlib.h> 00032 00033 /* Get memcpy, strdup, strlen. */ 00034 #include <string.h> 00035 00036 /* Get gc_hmac_md5. */ 00037 #include <gc.h> 00038 00039 #define MD5LEN 16 00040 #define SASL_INTEGRITY_PREFIX_LENGTH 4 00041 #define MAC_DATA_LEN 4 00042 #define MAC_HMAC_LEN 10 00043 #define MAC_MSG_TYPE "\x00\x01" 00044 #define MAC_MSG_TYPE_LEN 2 00045 #define MAC_SEQNUM_LEN 4 00046 00047 int 00048 digest_md5_encode (const char *input, size_t input_len, 00049 char **output, size_t * output_len, 00050 digest_md5_qop qop, 00051 unsigned long sendseqnum, char key[DIGEST_MD5_LENGTH]) 00052 { 00053 int res; 00054 00055 if (qop & DIGEST_MD5_QOP_AUTH_CONF) 00056 { 00057 return -1; 00058 } 00059 else if (qop & DIGEST_MD5_QOP_AUTH_INT) 00060 { 00061 char *seqnumin; 00062 char hash[GC_MD5_DIGEST_SIZE]; 00063 size_t len; 00064 00065 seqnumin = malloc (MAC_SEQNUM_LEN + input_len); 00066 if (seqnumin == NULL) 00067 return -1; 00068 00069 seqnumin[0] = (sendseqnum >> 24) & 0xFF; 00070 seqnumin[1] = (sendseqnum >> 16) & 0xFF; 00071 seqnumin[2] = (sendseqnum >> 8) & 0xFF; 00072 seqnumin[3] = sendseqnum & 0xFF; 00073 memcpy (seqnumin + MAC_SEQNUM_LEN, input, input_len); 00074 00075 res = gc_hmac_md5 (key, MD5LEN, 00076 seqnumin, MAC_SEQNUM_LEN + input_len, hash); 00077 free (seqnumin); 00078 if (res) 00079 return -1; 00080 00081 *output_len = MAC_DATA_LEN + input_len + MAC_HMAC_LEN + 00082 MAC_MSG_TYPE_LEN + MAC_SEQNUM_LEN; 00083 *output = malloc (*output_len); 00084 if (!*output) 00085 return -1; 00086 00087 len = MAC_DATA_LEN; 00088 memcpy (*output + len, input, input_len); 00089 len += input_len; 00090 memcpy (*output + len, hash, MAC_HMAC_LEN); 00091 len += MAC_HMAC_LEN; 00092 memcpy (*output + len, MAC_MSG_TYPE, MAC_MSG_TYPE_LEN); 00093 len += MAC_MSG_TYPE_LEN; 00094 (*output + len)[0] = (sendseqnum >> 24) & 0xFF; 00095 (*output + len)[1] = (sendseqnum >> 16) & 0xFF; 00096 (*output + len)[2] = (sendseqnum >> 8) & 0xFF; 00097 (*output + len)[3] = sendseqnum & 0xFF; 00098 len += MAC_SEQNUM_LEN; 00099 (*output)[0] = ((len - MAC_DATA_LEN) >> 24) & 0xFF; 00100 (*output)[1] = ((len - MAC_DATA_LEN) >> 16) & 0xFF; 00101 (*output)[2] = ((len - MAC_DATA_LEN) >> 8) & 0xFF; 00102 (*output)[3] = (len - MAC_DATA_LEN) & 0xFF; 00103 } 00104 else 00105 { 00106 *output_len = input_len; 00107 *output = malloc (input_len); 00108 if (!*output) 00109 return -1; 00110 memcpy (*output, input, input_len); 00111 } 00112 00113 return 0; 00114 } 00115 00116 #define C2I(buf) ((buf[3] & 0xFF) | \ 00117 ((buf[2] & 0xFF) << 8) | \ 00118 ((buf[1] & 0xFF) << 16) | \ 00119 ((buf[0] & 0xFF) << 24)) 00120 00121 int 00122 digest_md5_decode (const char *input, size_t input_len, 00123 char **output, size_t * output_len, 00124 digest_md5_qop qop, 00125 unsigned long readseqnum, char key[DIGEST_MD5_LENGTH]) 00126 { 00127 if (qop & DIGEST_MD5_QOP_AUTH_CONF) 00128 { 00129 return -1; 00130 } 00131 else if (qop & DIGEST_MD5_QOP_AUTH_INT) 00132 { 00133 char *seqnumin; 00134 char hash[GC_MD5_DIGEST_SIZE]; 00135 unsigned long len; 00136 char tmpbuf[SASL_INTEGRITY_PREFIX_LENGTH]; 00137 int res; 00138 00139 if (input_len < SASL_INTEGRITY_PREFIX_LENGTH) 00140 return -2; 00141 00142 len = C2I (input); 00143 00144 if (input_len < SASL_INTEGRITY_PREFIX_LENGTH + len) 00145 return -2; 00146 00147 len -= MAC_HMAC_LEN + MAC_MSG_TYPE_LEN + MAC_SEQNUM_LEN; 00148 00149 seqnumin = malloc (SASL_INTEGRITY_PREFIX_LENGTH + len); 00150 if (seqnumin == NULL) 00151 return -1; 00152 00153 tmpbuf[0] = (readseqnum >> 24) & 0xFF; 00154 tmpbuf[1] = (readseqnum >> 16) & 0xFF; 00155 tmpbuf[2] = (readseqnum >> 8) & 0xFF; 00156 tmpbuf[3] = readseqnum & 0xFF; 00157 00158 memcpy (seqnumin, tmpbuf, SASL_INTEGRITY_PREFIX_LENGTH); 00159 memcpy (seqnumin + SASL_INTEGRITY_PREFIX_LENGTH, 00160 input + MAC_DATA_LEN, len); 00161 00162 res = gc_hmac_md5 (key, MD5LEN, seqnumin, MAC_SEQNUM_LEN + len, hash); 00163 free (seqnumin); 00164 if (res) 00165 return -1; 00166 00167 if (memcmp 00168 (hash, 00169 input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN - 00170 MAC_HMAC_LEN, MAC_HMAC_LEN) == 0 00171 && memcmp (MAC_MSG_TYPE, 00172 input + input_len - MAC_SEQNUM_LEN - MAC_MSG_TYPE_LEN, 00173 MAC_MSG_TYPE_LEN) == 0 00174 && memcmp (tmpbuf, input + input_len - MAC_SEQNUM_LEN, 00175 MAC_SEQNUM_LEN) == 0) 00176 { 00177 *output_len = len; 00178 *output = malloc (*output_len); 00179 if (!*output) 00180 return -1; 00181 memcpy (*output, input + MAC_DATA_LEN, len); 00182 } 00183 else 00184 return -1; 00185 } 00186 else 00187 { 00188 *output_len = input_len; 00189 *output = malloc (input_len); 00190 if (!*output) 00191 return -1; 00192 memcpy (*output, input, input_len); 00193 } 00194 00195 return 0; 00196 }
1.7.6.1