~ubuntu-branches/ubuntu/jaunty/gnupg2/jaunty

« back to all changes in this revision

Viewing changes to g10/cipher.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Mueller
  • Date: 2005-03-29 10:30:32 UTC
  • Revision ID: james.westby@ubuntu.com-20050329103032-sj42n2ain3ipx310
Tags: upstream-1.9.15
ImportĀ upstreamĀ versionĀ 1.9.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* cipher.c - En-/De-ciphering filter
 
2
 * Copyright (C) 1998, 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
 
3
 *
 
4
 * This file is part of GnuPG.
 
5
 *
 
6
 * GnuPG is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * GnuPG is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
 
19
 */
 
20
 
 
21
#include <config.h>
 
22
#include <stdio.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <errno.h>
 
26
#include <assert.h>
 
27
 
 
28
#include "gpg.h"
 
29
#include "errors.h"
 
30
#include "iobuf.h"
 
31
#include "memory.h"
 
32
#include "util.h"
 
33
#include "filter.h"
 
34
#include "packet.h"
 
35
#include "options.h"
 
36
#include "main.h"
 
37
#include "status.h"
 
38
 
 
39
 
 
40
#define MIN_PARTIAL_SIZE 512
 
41
 
 
42
 
 
43
static void
 
44
write_header( cipher_filter_context_t *cfx, iobuf_t a )
 
45
{
 
46
    PACKET pkt;
 
47
    PKT_encrypted ed;
 
48
    byte temp[18];
 
49
    unsigned int blocksize;
 
50
    unsigned int nprefix;
 
51
    gpg_error_t rc;
 
52
 
 
53
    blocksize = gcry_cipher_get_algo_blklen ( cfx->dek->algo );
 
54
    if( blocksize < 8 || blocksize > 16 )
 
55
        log_fatal("unsupported blocksize %u\n", blocksize );
 
56
 
 
57
    memset( &ed, 0, sizeof ed );
 
58
    ed.len = cfx->datalen;
 
59
    ed.extralen = blocksize+2;
 
60
    ed.new_ctb = !ed.len && !RFC1991;
 
61
    if( cfx->dek->use_mdc ) {
 
62
        ed.mdc_method = DIGEST_ALGO_SHA1;
 
63
        gcry_md_open (&cfx->mdc_hash, GCRY_MD_SHA1, 0 );
 
64
        if ( DBG_HASHING )
 
65
            gcry_md_start_debug ( cfx->mdc_hash, "creatmdc" );
 
66
    }
 
67
 
 
68
    {
 
69
        char buf[20];
 
70
        
 
71
        sprintf (buf, "%d %d", ed.mdc_method, cfx->dek->algo);
 
72
        write_status_text (STATUS_BEGIN_ENCRYPTION, buf);
 
73
    }
 
74
 
 
75
    init_packet( &pkt );
 
76
    pkt.pkttype = cfx->dek->use_mdc? PKT_ENCRYPTED_MDC : PKT_ENCRYPTED;
 
77
    pkt.pkt.encrypted = &ed;
 
78
    if( build_packet( a, &pkt ))
 
79
        log_bug("build_packet(ENCR_DATA) failed\n");
 
80
    nprefix = blocksize;
 
81
    gcry_randomize ( temp, nprefix, GCRY_STRONG_RANDOM);
 
82
    temp[nprefix] = temp[nprefix-2];
 
83
    temp[nprefix+1] = temp[nprefix-1];
 
84
    print_cipher_algo_note( cfx->dek->algo );
 
85
    rc = gcry_cipher_open (&cfx->cipher_hd, cfx->dek->algo,
 
86
                           GCRY_CIPHER_MODE_CFB,
 
87
                           GCRY_CIPHER_SECURE
 
88
                           | ((cfx->dek->use_mdc || cfx->dek->algo >= 100) ?
 
89
                              0 : GCRY_CIPHER_ENABLE_SYNC));
 
90
    if (rc) {
 
91
        /* we should never get an error here cause we already checked, that
 
92
         * the algorithm is available. */
 
93
        BUG();
 
94
    }
 
95
/*   log_hexdump( "thekey", cfx->dek->key, cfx->dek->keylen );*/
 
96
    gcry_cipher_setkey( cfx->cipher_hd, cfx->dek->key, cfx->dek->keylen );
 
97
    gcry_cipher_setiv( cfx->cipher_hd, NULL, 0 );
 
98
/*  log_hexdump( "prefix", temp, nprefix+2 ); */
 
99
    if( cfx->mdc_hash ) /* hash the "IV" */
 
100
        gcry_md_write( cfx->mdc_hash, temp, nprefix+2 );
 
101
    gcry_cipher_encrypt( cfx->cipher_hd, temp, nprefix+2, NULL, 0);
 
102
    gcry_cipher_sync( cfx->cipher_hd );
 
103
    iobuf_write(a, temp, nprefix+2);
 
104
    cfx->header=1;
 
105
}
 
106
 
 
107
 
 
108
 
 
109
/****************
 
110
 * This filter is used to en/de-cipher data with a conventional algorithm
 
111
 */
 
112
int
 
113
cipher_filter( void *opaque, int control,
 
114
               iobuf_t a, byte *buf, size_t *ret_len)
 
115
{
 
116
    size_t size = *ret_len;
 
117
    cipher_filter_context_t *cfx = opaque;
 
118
    int rc=0;
 
119
 
 
120
    if( control == IOBUFCTRL_UNDERFLOW ) { /* decrypt */
 
121
        rc = -1; /* not yet used */
 
122
    }
 
123
    else if( control == IOBUFCTRL_FLUSH ) { /* encrypt */
 
124
        assert(a);
 
125
        if( !cfx->header ) {
 
126
            write_header( cfx, a );
 
127
        }
 
128
        if( cfx->mdc_hash )
 
129
            gcry_md_write( cfx->mdc_hash, buf, size );
 
130
        gcry_cipher_encrypt( cfx->cipher_hd, buf, size, NULL, 0);
 
131
        rc = iobuf_write( a, buf, size );
 
132
    }
 
133
    else if( control == IOBUFCTRL_FREE ) {
 
134
        if( cfx->mdc_hash ) {
 
135
            byte *hash;
 
136
            int hashlen = gcry_md_get_algo_dlen (gcry_md_get_algo (
 
137
                                                            cfx->mdc_hash));
 
138
            byte temp[22];
 
139
 
 
140
            assert( hashlen == 20 );
 
141
            /* we must hash the prefix of the MDC packet here */
 
142
            temp[0] = 0xd3;
 
143
            temp[1] = 0x14;
 
144
            gcry_md_putc ( cfx->mdc_hash, temp[0] );
 
145
            gcry_md_putc ( cfx->mdc_hash, temp[1] );
 
146
 
 
147
            gcry_md_final ( cfx->mdc_hash );
 
148
            hash = gcry_md_read ( cfx->mdc_hash, 0 );
 
149
            memcpy(temp+2, hash, 20);
 
150
            gcry_cipher_encrypt( cfx->cipher_hd, temp, 22, NULL, 0 );
 
151
            gcry_md_close ( cfx->mdc_hash ); cfx->mdc_hash = NULL;
 
152
            rc = iobuf_write( a, temp, 22 );
 
153
            if (rc)
 
154
                log_error("writing MDC packet failed\n" );
 
155
        }
 
156
        gcry_cipher_close (cfx->cipher_hd);
 
157
    }
 
158
    else if( control == IOBUFCTRL_DESC ) {
 
159
        *(char**)buf = "cipher_filter";
 
160
    }
 
161
    return rc;
 
162
}
 
163
 
 
164
 
 
165