00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00061 #include <string.h>
00062
00063 #include "ipsec/ipsec.h"
00064 #include "ipsec/util.h"
00065 #include "ipsec/debug.h"
00066
00067 #include "ipsec/sa.h"
00068 #include "ipsec/des.h"
00069 #include "ipsec/md5.h"
00070 #include "ipsec/sha1.h"
00071
00072 #include "ipsec/esp.h"
00073
00074
00075 __u32 ipsec_esp_bitmap = 0;
00078 __u32 ipsec_esp_lastSeq = 0;
00090 __u8 ipsec_esp_get_padding(int len)
00091 {
00092 int padding ;
00093
00094 for(padding = 0; padding < 8; padding++)
00095 if(((len+padding) % 8) == 0)
00096 break ;
00097 return padding ;
00098 }
00099
00111 ipsec_status ipsec_esp_decapsulate(ipsec_ip_header *packet, int *offset, int *len, sad_entry *sa)
00112 {
00113 int ret_val = IPSEC_STATUS_NOT_INITIALIZED;
00114 __u8 ip_header_len ;
00115 int local_len ;
00116 int payload_offset ;
00117 int payload_len ;
00118 ipsec_ip_header *new_ip_packet ;
00119 esp_packet *esp_header ;
00120 char cbc_iv[IPSEC_ESP_IV_SIZE] ;
00121 unsigned char digest[IPSEC_MAX_AUTHKEY_LEN];
00122
00123 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00124 "ipsec_esp_decapsulate",
00125 ("packet=%p, *offset=%d, *len=%d sa=%p",
00126 (void *)packet, *offset, *len, (void *)sa)
00127 );
00128
00129 ip_header_len = (packet->v_hl & 0x0f) * 4 ;
00130 esp_header = (esp_packet*)(((char*)packet)+ip_header_len) ;
00131 payload_offset = ip_header_len + IPSEC_ESP_SPI_SIZE + IPSEC_ESP_SEQ_SIZE ;
00132 payload_len = ipsec_ntohs(packet->len) - ip_header_len - IPSEC_ESP_HDR_SIZE ;
00133
00134
00135 if(sa->auth_alg != 0)
00136 {
00137
00138
00139
00140 ret_val = ipsec_check_replay_window(ipsec_ntohl(esp_header->sequence), ipsec_esp_lastSeq, ipsec_esp_bitmap);
00141 if(ret_val != IPSEC_AUDIT_SUCCESS)
00142 {
00143 IPSEC_LOG_AUD("ipsec_esp_decapsulate", IPSEC_AUDIT_SEQ_MISMATCH, ("packet rejected by anti-replay check (lastSeq=%08lx, seq=%08lx, window size=%d)", ipsec_esp_lastSeq, ipsec_ntohl(esp_header->sequence), IPSEC_SEQ_MAX_WINDOW) );
00144 return ret_val;
00145 }
00146
00147
00148 switch(sa->auth_alg) {
00149
00150 case IPSEC_HMAC_MD5:
00151 hmac_md5((unsigned char *)esp_header, payload_len-IPSEC_AUTH_ICV+IPSEC_ESP_HDR_SIZE,
00152 (unsigned char *)sa->authkey, IPSEC_AUTH_MD5_KEY_LEN, (unsigned char *)&digest);
00153 ret_val = IPSEC_STATUS_SUCCESS;
00154 break;
00155 case IPSEC_HMAC_SHA1:
00156 hmac_sha1((unsigned char *)esp_header, payload_len-IPSEC_AUTH_ICV+IPSEC_ESP_HDR_SIZE,
00157 (unsigned char *)sa->authkey, IPSEC_AUTH_SHA1_KEY_LEN, (unsigned char *)&digest);
00158 ret_val = IPSEC_STATUS_SUCCESS;
00159 break;
00160 default:
00161 IPSEC_LOG_ERR("ipsec_esp_decapsulate", IPSEC_STATUS_FAILURE, ("unknown HASH algorithm for this ESP")) ;
00162 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_decapsulate", ("return = %d", IPSEC_STATUS_FAILURE) );
00163 return IPSEC_STATUS_FAILURE;
00164 }
00165
00166
00167 if(memcmp(((char*)esp_header)+IPSEC_ESP_HDR_SIZE+payload_len-IPSEC_AUTH_ICV, digest, IPSEC_AUTH_ICV) != 0) {
00168 IPSEC_LOG_ERR("ipsec_esp_decapsulate", IPSEC_STATUS_FAILURE, ("ESP ICV does not match")) ;
00169 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_decapsulate", ("return = %d", IPSEC_STATUS_FAILURE) );
00170 return IPSEC_STATUS_FAILURE;
00171 }
00172
00173
00174 payload_len -= IPSEC_AUTH_ICV ;
00175
00176
00177 ret_val = ipsec_update_replay_window(ipsec_ntohl(esp_header->sequence), (__u32 *)&ipsec_esp_lastSeq, (__u32 *)&ipsec_esp_bitmap);
00178 if(ret_val != IPSEC_AUDIT_SUCCESS)
00179 {
00180 IPSEC_LOG_AUD("ipsec_esp_decapsulate", IPSEC_AUDIT_SEQ_MISMATCH, ("packet rejected by anti-replay update (lastSeq=%08lx, seq=%08lx, window size=%d)", ipsec_esp_lastSeq, ipsec_ntohl(esp_header->sequence), IPSEC_SEQ_MAX_WINDOW) );
00181 return ret_val;
00182 }
00183
00184 }
00185
00186
00187
00188 if(sa->enc_alg == IPSEC_3DES)
00189 {
00190
00191 memcpy(cbc_iv, ((char*)packet)+payload_offset, IPSEC_ESP_IV_SIZE);
00192
00193
00194 cipher_3des_cbc(((char*)packet)+payload_offset + IPSEC_ESP_IV_SIZE, payload_len-IPSEC_ESP_IV_SIZE, (unsigned char *)sa->enckey, (char*)&cbc_iv,
00195 DES_DECRYPT, ((char*)packet)+payload_offset + IPSEC_ESP_IV_SIZE);
00196 }
00197
00198 *offset = payload_offset+IPSEC_ESP_IV_SIZE ;
00199
00200 new_ip_packet = (ipsec_ip_header*)(((char*)packet) + payload_offset + IPSEC_ESP_IV_SIZE) ;
00201 local_len = ipsec_ntohs(new_ip_packet->len) ;
00202
00203 if( (local_len < IPSEC_MIN_IPHDR_SIZE) || (local_len > IPSEC_MTU))
00204 {
00205 IPSEC_LOG_ERR("ipsec_esp_decapsulate", IPSEC_STATUS_FAILURE, ("decapsulated strange packet")) ;
00206 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_decapsulate", ("return = %d", IPSEC_STATUS_BAD_PACKET) );
00207 return IPSEC_STATUS_BAD_PACKET;
00208 }
00209 *len = local_len ;
00210
00211 sa->sequence_number++ ;
00212
00213 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_decapsulate", ("return = %d", IPSEC_STATUS_SUCCESS) );
00214 return IPSEC_STATUS_SUCCESS;
00215 }
00216
00230 ipsec_status ipsec_esp_encapsulate(ipsec_ip_header *packet, int *offset, int *len, sad_entry *sa, __u32 src_addr, __u32 dest_addr)
00231 {
00232 int ret_val = IPSEC_STATUS_NOT_INITIALIZED;
00233 __u8 tos ;
00234 int inner_len ;
00235 int payload_offset ;
00236 int payload_len ;
00237 __u8 padd_len ;
00238 __u8 *pos ;
00239 __u8 padd ;
00240 ipsec_ip_header *new_ip_header ;
00241 ipsec_esp_header *new_esp_header ;
00242 unsigned char iv[IPSEC_ESP_IV_SIZE] = {0xD4, 0xDB, 0xAB, 0x9A, 0x9A, 0xDB, 0xD1, 0x94} ;
00243 unsigned char cbc_iv[IPSEC_ESP_IV_SIZE] ;
00244 unsigned char digest[IPSEC_MAX_AUTHKEY_LEN];
00245
00246 IPSEC_LOG_TRC(IPSEC_TRACE_ENTER,
00247 "ipsec_esp_encapsulate",
00248 ("packet=%p, *offset=%d, *len=%d, sa=%p, src_addr=%lu, dest_addr=%lu",
00249 (void *)packet, *offset, *len, (void *)sa, src_addr, dest_addr)
00250 );
00251
00252
00253 new_ip_header = (ipsec_ip_header*)(((char*)packet) - IPSEC_ESP_IV_SIZE - IPSEC_ESP_HDR_SIZE - IPSEC_MIN_IPHDR_SIZE) ;
00254 new_esp_header = (ipsec_esp_header*)(((char*)packet) - IPSEC_ESP_IV_SIZE - IPSEC_ESP_HDR_SIZE) ;
00255 payload_offset = (((char*)packet) - ((char*)new_ip_header)) ;
00256
00257 inner_len = ipsec_ntohs(packet->len) ;
00258
00259
00260 tos = packet->tos ;
00261
00263
00264
00265 if (packet->ttl == 0)
00266 {
00267 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_encapsulate", ("return = %d", IPSEC_STATUS_TTL_EXPIRED) );
00268 return IPSEC_STATUS_TTL_EXPIRED;
00269 }
00270
00271
00272 padd_len = ipsec_esp_get_padding(inner_len+2) ;
00273 pos = ((char*)packet)+inner_len ;
00274 if(padd_len != 0)
00275 {
00276 padd = 1 ;
00277 while(padd <= padd_len)
00278 *pos++ = padd++ ;
00279 }
00280
00281
00282 *pos++ = padd_len ;
00283
00284 *pos = 0x04 ;
00285
00286 payload_len = inner_len+IPSEC_ESP_HDR_SIZE+IPSEC_ESP_IV_SIZE + padd_len + 2 ;
00287
00288
00289 if(sa->enc_alg == IPSEC_3DES)
00290 {
00291
00292 memcpy(cbc_iv, iv, IPSEC_ESP_IV_SIZE);
00293
00294
00295 cipher_3des_cbc((__u8 *)packet, inner_len+padd_len+2, (__u8 *)sa->enckey, (__u8 *)&cbc_iv,
00296 DES_ENCRYPT, (__u8 *)packet);
00297 }
00298
00299
00300 memcpy( ((char*)packet)-IPSEC_ESP_IV_SIZE, iv, IPSEC_ESP_IV_SIZE) ;
00301
00302
00303 new_esp_header->spi = sa->spi;
00305 sa->sequence_number++ ;
00306 new_esp_header->sequence_number = ipsec_htonl(sa->sequence_number) ;
00307
00308
00309 if(sa->auth_alg != 0)
00310 {
00311
00312 switch(sa->auth_alg) {
00313
00314 case IPSEC_HMAC_MD5:
00315 hmac_md5((unsigned char *)new_esp_header, payload_len,
00316 (unsigned char *)sa->authkey, IPSEC_AUTH_MD5_KEY_LEN, (unsigned char *)&digest);
00317 ret_val = IPSEC_STATUS_SUCCESS;
00318 break;
00319 case IPSEC_HMAC_SHA1:
00320 hmac_sha1((unsigned char *)new_esp_header, payload_len,
00321 (unsigned char *)sa->authkey, IPSEC_AUTH_SHA1_KEY_LEN, (unsigned char *)&digest);
00322 ret_val = IPSEC_STATUS_SUCCESS;
00323 break;
00324 default:
00325 IPSEC_LOG_ERR("ipsec_esp_encapsulate", IPSEC_STATUS_FAILURE, ("unknown HASH algorithm for this ESP")) ;
00326 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_encapsulate", ("return = %d", IPSEC_STATUS_FAILURE) );
00327 return IPSEC_STATUS_FAILURE;
00328 }
00329
00330
00331 memcpy(((char*)new_esp_header)+payload_len, digest, IPSEC_AUTH_ICV);
00332
00333
00334 payload_len += IPSEC_AUTH_ICV ;
00335 }
00336
00337
00338 new_ip_header->v_hl = 0x45 ;
00339 new_ip_header->tos = tos ;
00340
00341 new_ip_header->len = ipsec_htons(payload_len+ IPSEC_MIN_IPHDR_SIZE);
00342 new_ip_header->id = 1000 ;
00343 new_ip_header->offset = 0 ;
00344 new_ip_header->ttl = 64 ;
00345 new_ip_header->protocol = IPSEC_PROTO_ESP ;
00346 new_ip_header->chksum = 0 ;
00347 new_ip_header->src = src_addr ;
00348 new_ip_header->dest = dest_addr ;
00349
00350
00351 new_ip_header->chksum = ipsec_ip_chksum(new_ip_header, sizeof(ipsec_ip_header)) ;
00352
00353
00354 *offset = payload_offset*(-1) ;
00355 *len = payload_len + IPSEC_MIN_IPHDR_SIZE ;
00356
00357 IPSEC_LOG_TRC(IPSEC_TRACE_RETURN, "ipsec_esp_encapsulate", ("return = %d", IPSEC_STATUS_SUCCESS) );
00358 return IPSEC_STATUS_SUCCESS;
00359 }
00360