IDEA removed, signing works
[gnupg.git] / g10 / seckey-cert.c
1 /* seckey-cert.c -  secret key certifucate packet handling
2  *      Copyright (c) 1997 by Werner Koch (dd9jn)
3  *
4  * This file is part of G10.
5  *
6  * G10 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  * G10 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 <assert.h>
26 #include "util.h"
27 #include "memory.h"
28 #include "packet.h"
29 #include "mpi.h"
30 #include "keydb.h"
31 #include "cipher.h"
32
33
34 static u16
35 checksum( byte *p )
36 {
37     u16 n, a;
38
39     n = *p++ << 8;
40     n |= *p++;
41     for(a=0; n; n-- )
42         a += *p++;
43     return a;
44 }
45
46
47 /****************
48  * Check the secret key certificate
49  */
50 int
51 check_secret_key( PKT_seckey_cert *cert )
52 {
53     byte iv[8];
54     byte *mpibuf;
55     u16 n;
56     MPI temp_mpi;
57     int res;
58     u32 keyid[2];
59
60 #if  BLOWFISH_BLOCKSIZE != 8
61   #error unsupportted blocksize
62 #endif
63
64     if( cert->pubkey_algo != PUBKEY_ALGO_RSA )
65         return G10ERR_PUBKEY_ALGO; /* unsupport algorithm */
66
67     if( cert->d.rsa.is_protected ) { /* remove the protection */
68         DEK *dek = NULL;
69         BLOWFISH_context *blowfish_ctx=NULL;
70
71         switch( cert->d.rsa.protect_algo ) {
72           case CIPHER_ALGO_NONE:
73             log_bug("unprotect seckey_cert is flagged protected\n");
74             break;
75           case CIPHER_ALGO_BLOWFISH:
76             mpi_get_keyid( cert->d.rsa.rsa_n , keyid );
77             dek = get_passphrase_hash( keyid, NULL );
78
79             m_free(dek); /* pw is in secure memory, so m_free() burns it */
80             memset( iv, 0, BLOWFISH_BLOCKSIZE );
81             blowfish_ctx = m_alloc_secure( sizeof *blowfish_ctx );
82             blowfish_setiv( blowfish_ctx, iv );
83             blowfish_decode_cfb( blowfish_ctx,
84                                  cert->d.rsa.protect.blowfish.iv,
85                                  cert->d.rsa.protect.blowfish.iv, 8 );
86             cert->d.rsa.calc_csum = 0;
87           #define X(a) do {                                             \
88                     mpibuf = (byte*)cert->d.rsa.rsa_##a;                \
89                     n = ((mpibuf[0] << 8) | mpibuf[1])-2;               \
90                     blowfish_decode_cfb( blowfish_ctx,                  \
91                                          mpibuf+4, mpibuf+4, n );       \
92                     cert->d.rsa.calc_csum += checksum( mpibuf );        \
93                     cert->d.rsa.rsa_##a = mpi_decode_buffer( mpibuf );  \
94                     m_free( mpibuf );                                   \
95                 } while(0)
96             X(d);
97             X(p);
98             X(q);
99             X(u);
100           #undef X
101             m_free( blowfish_ctx );
102             cert->d.rsa.is_protected = 0;
103           #if 0
104             #define X(a) do { printf("\tRSA " #a ": ");                   \
105                               mpi_print(stdout, cert->d.rsa.rsa_##a, 1 ); \
106                               putchar('\n');                              \
107                             } while(0)
108             X(n); X(e); X(d); X(p); X(q); X(u);
109             #undef X
110           #endif
111             /* now let's see wether we have used the right passphrase */
112             if( cert->d.rsa.calc_csum != cert->d.rsa.csum )
113                 return G10ERR_BAD_PASS;
114             temp_mpi = mpi_alloc(40);
115             mpi_mul(temp_mpi, cert->d.rsa.rsa_p, cert->d.rsa.rsa_q );
116             res = mpi_cmp( temp_mpi, cert->d.rsa.rsa_n );
117             mpi_free(temp_mpi);
118             if( res )
119                 return G10ERR_BAD_PASS;
120             break;
121
122           default:
123             return G10ERR_CIPHER_ALGO; /* unsupport protection algorithm */
124         }
125     }
126     /* must check the checksum here, because we didn't do it when
127      * parsing an unprotected certificate */
128     if( cert->d.rsa.calc_csum != cert->d.rsa.csum ) {
129         log_error("checksum in secret key certificate is wrong\n");
130         log_debug("stored csum=%04hx calculated csum=%04hx\n",
131                    cert->d.rsa.csum, cert->d.rsa.calc_csum );
132         return G10ERR_CHECKSUM;
133     }
134     return 0;
135 }
136
137