~ubuntu-branches/ubuntu/precise/libssh/precise

« back to all changes in this revision

Viewing changes to src/crypt.c

  • Committer: Bazaar Package Importer
  • Author(s): Laurent Bigonville
  • Date: 2011-06-15 15:48:07 UTC
  • mfrom: (1.1.10 upstream) (4.1.12 sid)
  • Revision ID: james.westby@ubuntu.com-20110615154807-3muklcqfftr1vtch
Tags: 0.5.0-2
* debian/patches/0002-Check-for-NULL-pointers-in-string-c.patch:
  Consolidate patch (Should fix previous REJECT)
* Support multiarch spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * crypt.c - blowfish-cbc code
 
3
 *
 
4
 * This file is part of the SSH Library
 
5
 *
 
6
 * Copyright (c) 2003 by Aris Adamantiadis
 
7
 *
 
8
 * The SSH Library is free software; you can redistribute it and/or modify
 
9
 * it under the terms of the GNU Lesser General Public License as published by
 
10
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 
11
 * option) any later version.
 
12
 *
 
13
 * The SSH Library is distributed in the hope that it will be useful, but
 
14
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 
15
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 
16
 * License for more details.
 
17
 *
 
18
 * You should have received a copy of the GNU Lesser General Public License
 
19
 * along with the SSH Library; see the file COPYING.  If not, write to
 
20
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
 
21
 * MA 02111-1307, USA.
 
22
 */
 
23
 
 
24
#include "config.h"
 
25
#include <stdlib.h>
 
26
#include <stdio.h>
 
27
#include <string.h>
 
28
 
 
29
#ifndef _WIN32
 
30
#include <arpa/inet.h>
 
31
#endif
 
32
 
 
33
#ifdef OPENSSL_CRYPTO
 
34
#include <openssl/blowfish.h>
 
35
#include <openssl/evp.h>
 
36
#include <openssl/hmac.h>
 
37
#endif
 
38
 
 
39
#include "libssh/priv.h"
 
40
#include "libssh/session.h"
 
41
#include "libssh/wrapper.h"
 
42
#include "libssh/crypto.h"
 
43
#include "libssh/buffer.h"
 
44
 
 
45
uint32_t packet_decrypt_len(ssh_session session, char *crypted){
 
46
  uint32_t decrypted;
 
47
 
 
48
  if (session->current_crypto) {
 
49
    if (packet_decrypt(session, crypted,
 
50
          session->current_crypto->in_cipher->blocksize) < 0) {
 
51
      return 0;
 
52
    }
 
53
  }
 
54
 
 
55
  memcpy(&decrypted,crypted,sizeof(decrypted));
 
56
  ssh_log(session, SSH_LOG_PACKET,
 
57
      "Packet size decrypted: %lu (0x%lx)",
 
58
      (long unsigned int) ntohl(decrypted),
 
59
      (long unsigned int) ntohl(decrypted));
 
60
  return ntohl(decrypted);
 
61
}
 
62
 
 
63
int packet_decrypt(ssh_session session, void *data,uint32_t len) {
 
64
  struct crypto_struct *crypto = session->current_crypto->in_cipher;
 
65
  char *out = NULL;
 
66
  if(len % session->current_crypto->in_cipher->blocksize != 0){
 
67
    ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
 
68
    return SSH_ERROR;
 
69
  }
 
70
  out = malloc(len);
 
71
  if (out == NULL) {
 
72
    return -1;
 
73
  }
 
74
 
 
75
  ssh_log(session,SSH_LOG_PACKET, "Decrypting %d bytes", len);
 
76
 
 
77
#ifdef HAVE_LIBGCRYPT
 
78
  if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey,
 
79
        session->current_crypto->decryptIV) < 0) {
 
80
    SAFE_FREE(out);
 
81
    return -1;
 
82
  }
 
83
  crypto->cbc_decrypt(crypto,data,out,len);
 
84
#elif defined HAVE_LIBCRYPTO
 
85
  if (crypto->set_decrypt_key(crypto, session->current_crypto->decryptkey) < 0) {
 
86
    SAFE_FREE(out);
 
87
    return -1;
 
88
  }
 
89
  crypto->cbc_decrypt(crypto,data,out,len,session->current_crypto->decryptIV);
 
90
#endif
 
91
 
 
92
  memcpy(data,out,len);
 
93
  memset(out,0,len);
 
94
 
 
95
  SAFE_FREE(out);
 
96
  return 0;
 
97
}
 
98
 
 
99
unsigned char *packet_encrypt(ssh_session session, void *data, uint32_t len) {
 
100
  struct crypto_struct *crypto = NULL;
 
101
  HMACCTX ctx = NULL;
 
102
  char *out = NULL;
 
103
  unsigned int finallen;
 
104
  uint32_t seq;
 
105
 
 
106
  if (!session->current_crypto) {
 
107
    return NULL; /* nothing to do here */
 
108
  }
 
109
  if(len % session->current_crypto->in_cipher->blocksize != 0){
 
110
      ssh_set_error(session, SSH_FATAL, "Cryptographic functions must be set on at least one blocksize (received %d)",len);
 
111
      return NULL;
 
112
  }
 
113
  out = malloc(len);
 
114
  if (out == NULL) {
 
115
    return NULL;
 
116
  }
 
117
 
 
118
  seq = ntohl(session->send_seq);
 
119
  crypto = session->current_crypto->out_cipher;
 
120
 
 
121
  ssh_log(session, SSH_LOG_PACKET, 
 
122
      "Encrypting packet with seq num: %d, len: %d",
 
123
      session->send_seq,len);
 
124
 
 
125
#ifdef HAVE_LIBGCRYPT
 
126
  if (crypto->set_encrypt_key(crypto, session->current_crypto->encryptkey,
 
127
      session->current_crypto->encryptIV) < 0) {
 
128
    SAFE_FREE(out);
 
129
    return NULL;
 
130
  }
 
131
#elif defined HAVE_LIBCRYPTO
 
132
  if (crypto->set_encrypt_key(crypto, session->current_crypto->encryptkey) < 0) {
 
133
    SAFE_FREE(out);
 
134
    return NULL;
 
135
  }
 
136
#endif
 
137
 
 
138
  if (session->version == 2) {
 
139
    ctx = hmac_init(session->current_crypto->encryptMAC,20,HMAC_SHA1);
 
140
    if (ctx == NULL) {
 
141
      SAFE_FREE(out);
 
142
      return NULL;
 
143
    }
 
144
    hmac_update(ctx,(unsigned char *)&seq,sizeof(uint32_t));
 
145
    hmac_update(ctx,data,len);
 
146
    hmac_final(ctx,session->current_crypto->hmacbuf,&finallen);
 
147
#ifdef DEBUG_CRYPTO
 
148
    ssh_print_hexa("mac: ",data,len);
 
149
    if (finallen != 20) {
 
150
      printf("Final len is %d\n",finallen);
 
151
    }
 
152
    ssh_print_hexa("Packet hmac", session->current_crypto->hmacbuf, 20);
 
153
#endif
 
154
  }
 
155
 
 
156
#ifdef HAVE_LIBGCRYPT
 
157
  crypto->cbc_encrypt(crypto, data, out, len);
 
158
#elif defined HAVE_LIBCRYPTO
 
159
  crypto->cbc_encrypt(crypto, data, out, len,
 
160
      session->current_crypto->encryptIV);
 
161
#endif
 
162
 
 
163
  memcpy(data, out, len);
 
164
  memset(out, 0, len);
 
165
  SAFE_FREE(out);
 
166
 
 
167
  if (session->version == 2) {
 
168
    return session->current_crypto->hmacbuf;
 
169
  }
 
170
 
 
171
  return NULL;
 
172
}
 
173
 
 
174
/**
 
175
 * @internal
 
176
 *
 
177
 * @brief Verify the hmac of a packet
 
178
 *
 
179
 * @param  session      The session to use.
 
180
 * @param  buffer       The buffer to verify the hmac from.
 
181
 * @param  mac          The mac to compare with the hmac.
 
182
 *
 
183
 * @return              0 if hmac and mac are equal, < 0 if not or an error
 
184
 *                      occurred.
 
185
 */
 
186
int packet_hmac_verify(ssh_session session, ssh_buffer buffer,
 
187
    unsigned char *mac) {
 
188
  unsigned char hmacbuf[EVP_MAX_MD_SIZE] = {0};
 
189
  HMACCTX ctx;
 
190
  unsigned int len;
 
191
  uint32_t seq;
 
192
 
 
193
  ctx = hmac_init(session->current_crypto->decryptMAC, 20, HMAC_SHA1);
 
194
  if (ctx == NULL) {
 
195
    return -1;
 
196
  }
 
197
 
 
198
  seq = htonl(session->recv_seq);
 
199
 
 
200
  hmac_update(ctx, (unsigned char *) &seq, sizeof(uint32_t));
 
201
  hmac_update(ctx, buffer_get_rest(buffer), buffer_get_rest_len(buffer));
 
202
  hmac_final(ctx, hmacbuf, &len);
 
203
 
 
204
#ifdef DEBUG_CRYPTO
 
205
  ssh_print_hexa("received mac",mac,len);
 
206
  ssh_print_hexa("Computed mac",hmacbuf,len);
 
207
  ssh_print_hexa("seq",(unsigned char *)&seq,sizeof(uint32_t));
 
208
#endif
 
209
  if (memcmp(mac, hmacbuf, len) == 0) {
 
210
    return 0;
 
211
  }
 
212
 
 
213
  return -1;
 
214
}
 
215
 
 
216
/* vim: set ts=2 sw=2 et cindent: */