50
52
char hexgrip[40+4+1];
52
55
for (i=0; i < 20; i++)
53
56
sprintf (hexgrip+2*i, "%02X", grip[i]);
54
57
strcpy (hexgrip+40, ".key");
56
59
fname = make_filename (opt.homedir, GNUPG_PRIVATE_KEYS_DIR, hexgrip, NULL);
58
fp = fopen (fname, "wb");
61
if (!force && !access (fname, F_OK))
63
if (!access (fname, F_OK))
65
log_error ("secret key file `%s' already exists\n", fname);
67
return gpg_error (GPG_ERR_GENERAL);
70
/* We would like to create FNAME but only if it does not already
71
exist. We cannot make this guarantee just using POSIX (GNU
72
provides the "x" opentype for fopen, however, this is not
73
portable). Thus, we use the more flexible open function and
74
then use fdopen to obtain a stream.
76
The mode parameter to open is what fopen uses. It will be
77
combined with the process' umask automatically. */
78
fd = open (fname, O_CREAT | O_EXCL | O_RDWR,
63
log_error ("secret key file `%s' already exists\n", fname);
65
return gpg_error (GPG_ERR_GENERAL);
68
/* In FORCE mode we would like to create FNAME but only if it does
69
not already exist. We cannot make this guarantee just using
70
POSIX (GNU provides the "x" opentype for fopen, however, this is
71
not portable). Thus, we use the more flexible open function and
72
then use fdopen to obtain a stream. */
73
fd = open (fname, force? (O_CREAT | O_TRUNC | O_WRONLY)
74
: (O_CREAT | O_EXCL | O_WRONLY),
80
76
#ifndef HAVE_W32_SYSTEM
81
| S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH
88
fp = fdopen (fd, "wb");
84
fp = fdopen (fd, "wb");
138
/* Modify a Key description, replacing certain special format
139
characters. List of currently supported replacements:
141
%% - Replaced by a single %
142
%c - Replaced by the content of COMMENT.
144
The functions returns 0 on success or an error code. On success a
145
newly allocated string is stored at the address of RESULT.
148
modify_description (const char *in, const char *comment, char **result)
150
size_t comment_length;
157
comment_length = strlen (comment);
158
in_len = strlen (in);
160
/* First pass calculates the length, second pass does the actual
164
for (pass=0; pass < 2; pass++)
167
for (i = 0; i < in_len; i++)
181
case 'c': /* Comment. */
184
memcpy (out, comment, comment_length);
185
out += comment_length;
188
out_len += comment_length;
191
default: /* Invalid special sequences are kept as they are. */
202
else if (in[i] == '%')
215
*result = out = xtrymalloc (out_len + 1);
217
return gpg_error_from_errno (errno);
222
assert (*result + out_len == out);
143
228
/* Unprotect the canconical encoded S-expression key in KEYBUF. GRIP
144
229
should be the hex encoded keygrip of that key to be used with the
145
230
caching mechanism. DESC_TEXT may be set to override the default
146
231
description used for the pinentry. */
148
unprotect (CTRL ctrl, const char *desc_text,
149
unsigned char **keybuf, const unsigned char *grip, int ignore_cache)
233
unprotect (ctrl_t ctrl, const char *desc_text,
234
unsigned char **keybuf, const unsigned char *grip,
235
cache_mode_t cache_mode)
151
237
struct pin_entry_info_s *pi;
152
238
struct try_unprotect_arg_s arg;
206
/* Return the secret key as an S-Exp in RESULT after locating it using
207
the grip. Returns NULL in RESULT if the operation should be
208
diverted to a token; SHADOW_INFO will point then to an allocated
209
S-Expression with the shadow_info part from the file. With
210
IGNORE_CACHE passed as true the passphrase is not taken from the
211
cache. DESC_TEXT may be set to present a custom description for the
214
agent_key_from_file (CTRL ctrl, const char *desc_text,
215
const unsigned char *grip, unsigned char **shadow_info,
216
int ignore_cache, gcry_sexp_t *result)
295
/* Read the key identified by GRIP from the private key directory and
296
return it as an gcrypt S-expression object in RESULT. On failure
297
returns an error code and stores NULL at RESULT. */
299
read_key_file (const unsigned char *grip, gcry_sexp_t *result)
222
305
unsigned char *buf;
223
size_t len, buflen, erroff;
306
size_t buflen, erroff;
224
307
gcry_sexp_t s_skey;
225
308
char hexgrip[40+4+1];
226
int got_shadow_info = 0;
232
312
for (i=0; i < 20; i++)
233
313
sprintf (hexgrip+2*i, "%02X", grip[i]);
274
355
(unsigned int)erroff, gpg_strerror (rc));
363
/* Return the secret key as an S-Exp in RESULT after locating it using
364
the grip. Returns NULL in RESULT if the operation should be
365
diverted to a token; SHADOW_INFO will point then to an allocated
366
S-Expression with the shadow_info part from the file. CACHE_MODE
367
defines now the cache shall be used. DESC_TEXT may be set to
368
present a custom description for the pinentry. */
370
agent_key_from_file (ctrl_t ctrl, const char *desc_text,
371
const unsigned char *grip, unsigned char **shadow_info,
372
cache_mode_t cache_mode, gcry_sexp_t *result)
376
size_t len, buflen, erroff;
378
int got_shadow_info = 0;
384
rc = read_key_file (grip, &s_skey);
388
/* For use with the protection functions we also need the key as an
389
canonical encoded S-expression in abuffer. Create this buffer
277
391
len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, NULL, 0);
279
393
buf = xtrymalloc (len);
396
rc = gpg_error_from_errno (errno);
283
397
gcry_sexp_release (s_skey);
286
400
len = gcry_sexp_sprint (s_skey, GCRYSEXP_FMT_CANON, buf, len);
288
gcry_sexp_release (s_skey);
290
404
switch (agent_private_key_type (buf))
292
406
case PRIVATE_KEY_CLEAR:
293
407
break; /* no unprotection needed */
294
408
case PRIVATE_KEY_PROTECTED:
295
rc = unprotect (ctrl, desc_text, &buf, grip, ignore_cache);
297
log_error ("failed to unprotect the secret key: %s\n",
410
gcry_sexp_t comment_sexp;
411
size_t comment_length;
412
char *desc_text_final;
413
const char *comment = NULL;
415
/* Note, that we will take the comment as a C string for
416
display purposes; i.e. all stuff beyond a Nul character is
418
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
420
comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
427
desc_text_final = NULL;
430
if (comment[comment_length])
432
/* Not a C-string; create one. We might here allocate
433
more than actually displayed but well, that
434
shouldn't be a problem. */
435
char *tmp = xtrymalloc (comment_length+1);
437
rc = gpg_error_from_errno (errno);
440
memcpy (tmp, comment, comment_length);
441
tmp[comment_length] = 0;
442
rc = modify_description (desc_text, tmp, &desc_text_final);
447
rc = modify_description (desc_text, comment, &desc_text_final);
452
rc = unprotect (ctrl, desc_text_final, &buf, grip, cache_mode);
454
log_error ("failed to unprotect the secret key: %s\n",
458
gcry_sexp_release (comment_sexp);
459
xfree (desc_text_final);
300
462
case PRIVATE_KEY_SHADOWED:
519
/* Return the public key for the keygrip GRIP. The result is stored
520
at RESULT. This function extracts the public key from the private
521
key database. On failure an error code is returned and NULL stored
524
agent_public_key_from_file (ctrl_t ctrl,
525
const unsigned char *grip,
530
const char *algoname;
531
gcry_sexp_t uri_sexp, comment_sexp;
532
const char *uri, *comment;
533
size_t uri_length, comment_length;
535
void *args[4+2+2+1]; /* Size is max. # of elements + 2 for uri + 2
536
for comment + end-of-list. */
538
gcry_sexp_t list, l2;
547
rc = read_key_file (grip, &s_skey);
551
list = gcry_sexp_find_token (s_skey, "shadowed-private-key", 0 );
553
list = gcry_sexp_find_token (s_skey, "protected-private-key", 0 );
555
list = gcry_sexp_find_token (s_skey, "private-key", 0 );
558
log_error ("invalid private key format\n");
559
gcry_sexp_release (s_skey);
560
return gpg_error (GPG_ERR_BAD_SECKEY);
563
l2 = gcry_sexp_cadr (list);
564
gcry_sexp_release (list);
566
name = gcry_sexp_nth_data (list, 0, &n);
567
if (n==3 && !memcmp (name, "rsa", 3))
572
else if (n==3 && !memcmp (name, "dsa", 3))
577
else if (n==3 && !memcmp (name, "elg", 3))
584
log_error ("unknown private key algorithm\n");
585
gcry_sexp_release (list);
586
gcry_sexp_release (s_skey);
587
return gpg_error (GPG_ERR_BAD_SECKEY);
590
/* Allocate an array for the parameters and copy them out of the
591
secret key. FIXME: We should have a generic copy function. */
592
array = xtrycalloc (strlen(elems) + 1, sizeof *array);
595
rc = gpg_error_from_errno (errno);
596
gcry_sexp_release (list);
597
gcry_sexp_release (s_skey);
601
for (idx=0, s=elems; *s; s++, idx++ )
603
l2 = gcry_sexp_find_token (list, s, 1);
606
/* Required parameter not found. */
607
for (i=0; i<idx; i++)
608
gcry_mpi_release (array[i]);
610
gcry_sexp_release (list);
611
gcry_sexp_release (s_skey);
612
return gpg_error (GPG_ERR_BAD_SECKEY);
614
array[idx] = gcry_sexp_nth_mpi (l2, 1, GCRYMPI_FMT_USG);
615
gcry_sexp_release (l2);
618
/* Required parameter is invalid. */
619
for (i=0; i<idx; i++)
620
gcry_mpi_release (array[i]);
622
gcry_sexp_release (list);
623
gcry_sexp_release (s_skey);
624
return gpg_error (GPG_ERR_BAD_SECKEY);
627
gcry_sexp_release (list);
632
uri_sexp = gcry_sexp_find_token (s_skey, "uri", 0);
634
uri = gcry_sexp_nth_data (uri_sexp, 1, &uri_length);
638
comment_sexp = gcry_sexp_find_token (s_skey, "comment", 0);
640
comment = gcry_sexp_nth_data (comment_sexp, 1, &comment_length);
642
gcry_sexp_release (s_skey);
646
/* FIXME: The following thing is pretty ugly code; we should
647
investigate how to make it cleaner. Probably code to handle
648
canonical S-expressions in a memory buffer is better suioted for
649
such a task. After all that is what we do in protect.c. Neeed
650
to find common patterns and write a straightformward API to use
652
assert (sizeof (size_t) <= sizeof (void*));
654
format = xtrymalloc (15+7*strlen (elems)+10+15+1+1);
657
rc = gpg_error_from_errno (errno);
658
for (i=0; array[i]; i++)
659
gcry_mpi_release (array[i]);
661
gcry_sexp_release (uri_sexp);
662
gcry_sexp_release (comment_sexp);
667
p = stpcpy (stpcpy (format, "(public-key("), algoname);
668
for (idx=0, s=elems; *s; s++, idx++ )
672
p = stpcpy (p, " %m)");
673
assert (argidx < DIM (args));
674
args[argidx++] = &array[idx];
679
p = stpcpy (p, "(uri %b)");
680
assert (argidx+1 < DIM (args));
681
args[argidx++] = (void *)uri_length;
682
args[argidx++] = (void *)uri;
686
p = stpcpy (p, "(comment %b)");
687
assert (argidx+1 < DIM (args));
688
args[argidx++] = (void *)comment_length;
689
args[argidx++] = (void*)comment;
693
assert (argidx < DIM (args));
696
rc = gcry_sexp_build_array (&list, NULL, format, args);
698
for (i=0; array[i]; i++)
699
gcry_mpi_release (array[i]);
701
gcry_sexp_release (uri_sexp);
702
gcry_sexp_release (comment_sexp);
353
711
/* Return the secret key as an S-Exp after locating it using the grip.
354
712
Returns NULL if key is not available. 0 = key is available */