Develop and Download Open Source Software

Browse Subversion Repository

Diff of /trunk/ttssh2/ttxssh/pkt.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 9254 by nmaya, Wed Dec 16 12:24:13 2020 UTC revision 9255 by nmaya, Wed May 19 14:11:26 2021 UTC
# Line 176  int PKT_recv(PTInstVar pvar, char *buf, Line 176  int PKT_recv(PTInstVar pvar, char *buf,
176                  }                  }
177                  else if (pvar->pkt_state.seen_server_ID && pvar->pkt_state.datalen >= SSH_get_min_packet_size(pvar)) {                  else if (pvar->pkt_state.seen_server_ID && pvar->pkt_state.datalen >= SSH_get_min_packet_size(pvar)) {
178                          char *data = pvar->pkt_state.buf + pvar->pkt_state.datastart;                          char *data = pvar->pkt_state.buf + pvar->pkt_state.datastart;
179                          uint32 padding;                          uint32 padding_size = 0;
180                          uint32 pktsize;                          uint32 pktsize = 0;
181                          uint32 total_packet_size;                          uint32 total_packet_size;
182                          struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;                          struct Mac *mac = &pvar->ssh2_keys[MODE_IN].mac;
183                          struct Enc *enc = &pvar->ssh2_keys[MODE_IN].enc;                          struct Enc *enc = &pvar->ssh2_keys[MODE_IN].enc;
184                          int aadlen;                          int authlen = 0, aadlen = 0;
185    
186                          /*                          if (SSHv2(pvar)) {
187                           * aadlen: Additional Authenticated Data Length                                  /*
188                           *   - 暗号化しないが MAC や AEAD での認証の対象となるデータの長さ                                   * pktsize
189                           *                                   *   uint32   packet_length
190                           * EtM 方式の MAC や、AEAD な暗号ではパケットの先頭のパケット長部分は暗号化されず                                   * は
191                           * 認証のみが行われる。パケット長は uint32 (4バイト) で格納されている。                                   *   byte     padding_length
192                           * 通常の MAC 方式 (E&M) で、かつ AEAD でない暗号方式ではパケット長部分も暗号化                                   *   byte[n1] payload; n1 = packet_length - padding_length - 1
193                           * されるので aadlen は 0 となる。                                   *   byte[n2] random padding; n2 = padding_length
194                           */                                   * の長さの合計で
195                          if (SSHv2(pvar) && ((mac && mac->etm) || (enc && enc->auth_len > 0))) {                                   *   byte[m]  mac (Message Authentication Code - MAC); m = mac_length
196                                  aadlen = 4;                                   * の長さを含まない。
197                                     * cf. RFC 4253 6. Binary Packet Protocol
198                                     */
199    
200                                    if (enc && enc->auth_len > 0) {
201                                            authlen = enc->auth_len;
202                                    }
203    
204                                    /*
205                                     *                      |          | lead 4 bytes are encrypted | aadlen |
206                                     * Encryption type
207                                     *   enc->auth_len >  0 | AEAD     | AES-GCM ... no             | 4      |     (2)
208                                     *                      |          | chacha20-poly1305 ... yes  | 4      | (1) (2)
209                                     *   enc->auth_len == 0 | not AEAD | depends on MAC type        | <-     |
210                                     * MAC type
211                                     *   mac->etm == true   | EtM      | no                         | 4      |
212                                     *   mac->etm == false  | E&M      | yes                        | 0      |
213                                     * (1) lead 4 bytes are encrypted separately from main part.
214                                     * (2) implicit MAC type of AEAD is EtM
215                                     */
216                                    /*
217                                     * aadlen: Additional Authenticated Data Length
218                                     *   MAC の対象となるデータと一緒に暗号化されない、"MAC の対象となるデータの長さ"のサイズ
219                                     *   この部分は packet_length で、uint32 (4バイト)
220                                     *
221                                     * - 通常の MAC 方式 (E&M) ではパケット長部分が一緒に暗号化されるので aadlen は 0 となる。
222                                     * - EtM 方式の MAC や AEAD の AES-GCM では、パケット長部分が暗号化されないので
223                                     * aadlen は 4 となる。
224                                     * - AEAD の chacha20-poly1305 ではパケット長部分が暗号化されるが、MAC の対象となるデータ
225                                     * とは別に暗号化されるので aadlen は 4 となる。
226                                     *
227                                     */
228                                    if ((mac && mac->etm) || authlen > 0) {
229                                            aadlen = 4;
230                                    }
231    
232                                    if (authlen > 0 &&
233                                        pvar->cc[MODE_IN]->cipher->id == SSH2_CIPHER_CHACHAPOLY) {
234                                            /*
235                                             * AEAD の chacha20-poly1305 ではパケット長部分が別に暗号化されている。
236                                             * この処理は長さを取得するが、data は暗号化されたままとなる。
237                                             */
238                                            chachapoly_get_length(pvar->cc[MODE_IN]->cp_ctx, &pktsize,
239                                                                  pvar->ssh_state.receiver_sequence_number,
240                                                                  data, pvar->pkt_state.datalen);
241                                    }
242                                    else if (authlen == 0 &&
243                                             aadlen == 0 &&
244                                             !pvar->pkt_state.predecrypted_packet && aadlen == 0) {
245                                            /*
246                                             * AEAD でなく E&M (aadlen が 0) の時は、暗号化されているパケット長を
247                                             * 知る必要が有るため、先頭の 1 ブロックだけ事前に復号する。
248                                             */
249                                            SSH_predecrypt_packet(pvar, data);
250                                            pvar->pkt_state.predecrypted_packet = TRUE;
251    
252                                            pktsize = get_uint32_MSBfirst(data);
253                                    }
254                                    else {
255                                            /*
256                                             * EtM 方式の MAC や、AEAD で AES-GCM のときなどはそのまま読める。
257                                             */
258                                            pktsize = get_uint32_MSBfirst(data);
259                                    }
260                          }                          }
261                          else {                          else {
262                                  aadlen = 0;                                  pktsize = get_uint32_MSBfirst(data);
263                          }                          }
264    
                         /*  
                          * aadlen が 0 の時はパケット長部分が暗号化されている。パケット全体を受信してから  
                          * 後段の処理を行う為にパケット長を知る必要が有る為、先頭の 1 ブロックを復号する。  
                          */  
                         if (SSHv2(pvar) && !pvar->pkt_state.predecrypted_packet && aadlen == 0) {  
                                 SSH_predecrypt_packet(pvar, data);  
                                 pvar->pkt_state.predecrypted_packet = TRUE;  
                         }  
   
                         // パケットの先頭に uint32 (4バイト) のパケット長が来る  
                         pktsize = get_uint32_MSBfirst(data);  
   
265                          if (SSHv1(pvar)) {                          if (SSHv1(pvar)) {
266                                  // SSH1 ではパケット長の値には padding の長さが含まれていない。                                  // SSH1 ではパケット長の値には padding の長さが含まれていない。
267                                  // また padding の長さの情報もパケット上には無いので、パケット長の値から計算する。                                  // また padding の長さの情報もパケット上には無いので、パケット長の値から計算する。
268                                  padding = 8 - (pktsize % 8);                                  padding_size = 8 - (pktsize % 8);
269    
270                                  // 以降の処理は pktsize に padding の値が含まれている事が前提となっている。                                  // 以降の処理は pktsize に padding_size の値が含まれている事が前提となっている。
271                                  pktsize += padding;                                  pktsize += padding_size;
272                          }                          }
273    
274                          // パケット(TCPペイロード)の全体のサイズは、SSHペイロード+4(+MAC)となる。                          // パケット(TCPペイロード)の全体のサイズは、
275                          // +4は、SSHペイロードのサイズを格納している部分(int型)。                          // 4(パケット長のサイズ)+パケット長(+MACのサイズ)となる。
276                          total_packet_size = pktsize + 4 + SSH_get_authdata_size(pvar, MODE_IN);                          total_packet_size = 4 + pktsize + SSH_get_authdata_size(pvar, MODE_IN);
277    
278                          if (total_packet_size <= pvar->pkt_state.datalen) {                          if (total_packet_size <= pvar->pkt_state.datalen) {
279                                  // 受信済みデータが十分有る場合はパケットの実処理を行う                                  // 受信済みデータが十分有る場合はパケットの実処理を行う
280                                  if (SSHv1(pvar)) {                                  if (SSHv1(pvar)) {
281                                          // SSH1 は EtM 非対応 (そもそも MAC ではなく CRC を使う)                                          // SSH1 は EtM 非対応 (そもそも MAC ではなく CRC を使う)
282                                          SSH1_handle_packet(pvar, data, pktsize, padding);                                          SSH1_handle_packet(pvar, data, pktsize, padding_size);
283                                  }                                  }
284                                  else {                                  else {
285                                          // SSH2 ではこの時点では padding 長部分が復号されていない場合があるので、                                          // SSH2 ではこの時点では padding 長部分が復号されていない場合があるので、
286                                          // padding 長は渡さずに、必要になった時に内部で取得する。                                          // padding 長は渡さずに、必要になった時に内部で取得する。
287                                          SSH2_handle_packet(pvar, data, pktsize, aadlen, enc->auth_len);                                          SSH2_handle_packet(pvar, data, pktsize, aadlen, authlen);
288                                  }                                  }
289    
290                                  pvar->pkt_state.predecrypted_packet = FALSE;                                  pvar->pkt_state.predecrypted_packet = FALSE;

Legend:
Removed from v.9254  
changed lines
  Added in v.9255

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26