patchlevel 2
[gnupg.git] / g10 / passphrase.c
1 /* passphrase.c -  Get a passphrase
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 "options.h"
29 #include "ttyio.h"
30 #include "cipher.h"
31 #include "keydb.h"
32
33 static int pwfd = -1;
34
35 static int hash_passphrase( DEK *dek, char *pw );
36
37 void
38 set_passphrase_fd( int fd )
39 {
40     pwfd = fd;
41 }
42
43 int
44 get_passphrase_fd()
45 {
46     return pwfd;
47 }
48
49
50 /****************
51  * Get a passphrase for the secret key with KEYID, display TEXT
52  * if the user needs to enter the passphrase.
53  * Returns: m_alloced md5 passphrase hash; caller must free
54  */
55 DEK *
56 get_passphrase_hash( u32 *keyid, char *text )
57 {
58     char *pw;
59     DEK *dek;
60
61     if( keyid && !opt.batch ) {
62         char *ustr;
63         tty_printf("Need a pass phrase to unlock the secret key for:\n");
64         tty_printf("  \"" );
65         ustr = get_user_id_string( keyid );
66         tty_print_string( ustr, strlen(ustr) );
67         m_free(ustr);
68         tty_printf("\"\n\n");
69
70     }
71     if( pwfd != -1 ) { /* read the passphrase from the given descriptor */
72         int i, len;
73
74         if( !opt.batch )
75             tty_printf("Reading from file descriptor %d ...", pwfd );
76         for( pw = NULL, i = len = 100; ; i++ ) {
77             if( i >= len-1 ) {
78                 char *pw2 = pw;
79                 len += 100;
80                 pw = m_alloc_secure( len );
81                 if( pw2 )
82                     memcpy(pw, pw2, i );
83                 i=0;
84             }
85             if( read( pwfd, pw+i, 1) != 1 || pw[i] == '\n' )
86                 break;
87         }
88         pw[i] = 0;
89         if( !opt.batch )
90             tty_printf("\b\b\b   \n" );
91     }
92     else if( opt.batch )
93         log_fatal("Can't query password in batchmode\n");
94     else {
95         pw = tty_get_hidden("Enter pass phrase: " );
96         tty_kill_prompt();
97     }
98     dek = m_alloc_secure( sizeof *dek );
99     dek->algo = CIPHER_ALGO_BLOWFISH;
100     if( hash_passphrase( dek, pw ) )
101         log_bug("get_passphrase_hash\n");
102     m_free(pw); /* is allocated in secure memory, so it will be burned */
103     return dek;
104 }
105
106
107 /****************
108  * This function is used to construct a DEK from a user input.
109  * It uses the default CIPHER
110  * Returns: 0 = okay, -1 No passphrase entered, > 0 error
111  */
112 int
113 make_dek_from_passphrase( DEK *dek, int mode )
114 {
115     char *pw, *pw2;
116     int rc=0;
117
118     pw = tty_get_hidden("Enter pass phrase: " );
119     tty_kill_prompt();
120     if( mode == 2 ) {
121         pw2 = tty_get_hidden("Repeat pass phrase: " );
122         tty_kill_prompt();
123         if( strcmp(pw, pw2) ) {
124             m_free(pw2);
125             m_free(pw);
126             return G10ERR_PASSPHRASE;
127         }
128         m_free(pw2);
129     }
130     if( !*pw )
131         rc = -1;
132     else
133         rc = hash_passphrase( dek, pw );
134     m_free(pw);
135     return rc;
136 }
137
138
139 static int
140 hash_passphrase( DEK *dek, char *pw )
141 {
142     int rc = 0;
143
144     dek->keylen = 0;
145     if( dek->algo == CIPHER_ALGO_BLOWFISH ) {
146         RMDHANDLE rmd;
147
148         rmd = rmd160_open(1);
149         rmd160_write( rmd, pw, strlen(pw) );
150         dek->keylen = 20;
151         memcpy( dek->key, rmd160_final(rmd), dek->keylen );
152         rmd160_close(rmd);
153     }
154     else
155         rc = G10ERR_UNSUPPORTED;
156     return rc;
157 }
158