mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-03 12:11:33 +01:00
* cardglue.c (send_status_info): Make CTRL optional.
(agent_scd_writekey, inq_writekey_parms): New. (agent_openpgp_storekey): Removed. * cardglue.h: Add a few more error code mappings. * keygen.c (copy_mpi): Removed. (save_unprotected_key_to_card): Changed to use agent_scd_writekey. * app-common.h, app-openpgp.c, tlv.c, tlv.h: Updated from newer version in gnupg 1.9 CVS.
This commit is contained in:
parent
bd644c8d45
commit
be2aa37dbf
17
NEWS
17
NEWS
@ -1,6 +1,23 @@
|
||||
Noteworthy changes in version 1.4.2
|
||||
------------------------------------------------
|
||||
|
||||
* New command "verify" in the card-edit menu to display
|
||||
the Private-DO-3. The Admin command has been enhanced to take
|
||||
the optional arguments "on", "off" and "verify". The latter may
|
||||
be used to verify the ADmin Pin without modifying data; this
|
||||
allows displayin the Private-DO-4 with the "list" command.
|
||||
|
||||
* Rewrote large parts of the card code to optionally make use of a
|
||||
running gpg-agent. If --use-agent is beeing used and a
|
||||
gpg-agent with enabled scdaemon is active, gpg will now divert
|
||||
all card operations to that daemon. This is required because
|
||||
bot, scdaemon and gpg require exclusive access to the card
|
||||
reader. By delegating the work to scdaemon, both can peacefully
|
||||
coexist and scdaemon is able to control the use of the reader.
|
||||
Note that this requires at least gnupg 1.9.17.
|
||||
|
||||
* Fixed a couple of problems with the card reader.
|
||||
|
||||
|
||||
Noteworthy changes in version 1.4.1 (2005-03-15)
|
||||
------------------------------------------------
|
||||
|
@ -1,3 +1,14 @@
|
||||
2005-05-21 Werner Koch <wk@g10code.com>
|
||||
|
||||
* cardglue.c (send_status_info): Make CTRL optional.
|
||||
(agent_scd_writekey, inq_writekey_parms): New.
|
||||
(agent_openpgp_storekey): Removed.
|
||||
* cardglue.h: Add a few more error code mappings.
|
||||
* keygen.c (copy_mpi): Removed.
|
||||
(save_unprotected_key_to_card): Changed to use agent_scd_writekey.
|
||||
* app-common.h, app-openpgp.c, tlv.c, tlv.h: Updated from newer
|
||||
version in gnupg 1.9 CVS.
|
||||
|
||||
2005-05-20 Werner Koch <wk@g10code.com>
|
||||
|
||||
* ccid-driver.c (ccid_transceive): Arghhh. The seqno is another
|
||||
|
@ -86,6 +86,11 @@ struct app_ctx_s {
|
||||
void *pincb_arg,
|
||||
const void *indata, size_t indatalen,
|
||||
unsigned char **outdata, size_t *outdatalen);
|
||||
gpg_error_t (*writekey) (app_t app, ctrl_t ctrl,
|
||||
const char *certid, unsigned int flags,
|
||||
gpg_error_t (*pincb)(void*,const char *,char **),
|
||||
void *pincb_arg,
|
||||
const unsigned char *pk, size_t pklen);
|
||||
gpg_error_t (*genkey) (app_t app, ctrl_t ctrl,
|
||||
const char *keynostr, unsigned int flags,
|
||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||
@ -148,6 +153,11 @@ gpg_error_t app_decipher (app_t app, const char *keyidstr,
|
||||
void *pincb_arg,
|
||||
const void *indata, size_t indatalen,
|
||||
unsigned char **outdata, size_t *outdatalen );
|
||||
gpg_error_t app_writekey (app_t app, ctrl_t ctrl,
|
||||
const char *keyidstr, unsigned int flags,
|
||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||
void *pincb_arg,
|
||||
const unsigned char *keydata, size_t keydatalen);
|
||||
gpg_error_t app_genkey (app_t app, ctrl_t ctrl,
|
||||
const char *keynostr, unsigned int flags,
|
||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||
|
@ -565,7 +565,7 @@ store_fpr (int slot, int keynumber, u32 timestamp,
|
||||
n = 6 + 2 + mlen + 2 + elen;
|
||||
p = buffer = xtrymalloc (3 + n);
|
||||
if (!buffer)
|
||||
return gpg_error (gpg_err_code_from_errno (errno));
|
||||
return gpg_error_from_errno (errno);
|
||||
|
||||
*p++ = 0x99; /* ctb */
|
||||
*p++ = n >> 8; /* 2 byte length header */
|
||||
@ -1527,6 +1527,318 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr, int reset_mode,
|
||||
}
|
||||
|
||||
|
||||
/* Check whether a key already exists. KEYIDX is the index of the key
|
||||
(0..2). If FORCE is TRUE a diagnositivc will be printed but no
|
||||
error returned if the key already exists. */
|
||||
static gpg_error_t
|
||||
does_key_exist (app_t app, int keyidx, int force)
|
||||
{
|
||||
const unsigned char *fpr;
|
||||
unsigned char *buffer;
|
||||
size_t buflen, n;
|
||||
int i;
|
||||
|
||||
assert (keyidx >=0 && keyidx <= 2);
|
||||
|
||||
if (iso7816_get_data (app->slot, 0x006E, &buffer, &buflen))
|
||||
{
|
||||
log_error (_("error reading application data\n"));
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
fpr = find_tlv (buffer, buflen, 0x00C5, &n);
|
||||
if (!fpr || n < 60)
|
||||
{
|
||||
log_error (_("error reading fingerprint DO\n"));
|
||||
xfree (buffer);
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
fpr += 20*keyidx;
|
||||
for (i=0; i < 20 && !fpr[i]; i++)
|
||||
;
|
||||
xfree (buffer);
|
||||
if (i!=20 && !force)
|
||||
{
|
||||
log_error (_("key already exists\n"));
|
||||
return gpg_error (GPG_ERR_EEXIST);
|
||||
}
|
||||
else if (i!=20)
|
||||
log_info (_("existing key will be replaced\n"));
|
||||
else
|
||||
log_info (_("generating new key\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Handle the WRITEKEY command for OpenPGP. This function expects a
|
||||
canonical encoded S-expression with the secret key in KEYDATA and
|
||||
its length (for assertions) in KEYDATALEN. KEYID needs to be the
|
||||
usual keyid which for OpenPGP is the string "OPENPGP.n" with
|
||||
n=1,2,3. Bit 0 of FLAGS indicates whether an existing key shall
|
||||
get overwritten. PINCB and PINCB_ARG are the usual arguments for
|
||||
the pinentry callback. */
|
||||
static gpg_error_t
|
||||
do_writekey (app_t app, ctrl_t ctrl,
|
||||
const char *keyid, unsigned int flags,
|
||||
gpg_error_t (*pincb)(void*, const char *, char **),
|
||||
void *pincb_arg,
|
||||
const unsigned char *keydata, size_t keydatalen)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int force = (flags & 1);
|
||||
int keyno;
|
||||
const unsigned char *buf, *tok;
|
||||
size_t buflen, toklen;
|
||||
int depth, last_depth1, last_depth2;
|
||||
const unsigned char *rsa_n = NULL;
|
||||
const unsigned char *rsa_e = NULL;
|
||||
const unsigned char *rsa_p = NULL;
|
||||
const unsigned char *rsa_q = NULL;
|
||||
size_t rsa_n_len, rsa_e_len, rsa_p_len, rsa_q_len;
|
||||
unsigned int nbits;
|
||||
unsigned char *template = NULL;
|
||||
unsigned char *tp;
|
||||
size_t template_len;
|
||||
unsigned char fprbuf[20];
|
||||
u32 created_at = 0;
|
||||
|
||||
if (!strcmp (keyid, "OPENPGP.1"))
|
||||
keyno = 0;
|
||||
else if (!strcmp (keyid, "OPENPGP.2"))
|
||||
keyno = 1;
|
||||
else if (!strcmp (keyid, "OPENPGP.3"))
|
||||
keyno = 2;
|
||||
else
|
||||
return gpg_error (GPG_ERR_INV_ID);
|
||||
|
||||
err = does_key_exist (app, keyno, force);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
/*
|
||||
Parse the S-expression
|
||||
*/
|
||||
buf = keydata;
|
||||
buflen = keydatalen;
|
||||
depth = 0;
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (!tok || toklen != 11 || memcmp ("private-key", tok, toklen))
|
||||
{
|
||||
if (!tok)
|
||||
;
|
||||
else if (toklen == 21 && !memcmp ("protected-private-key", tok, toklen))
|
||||
log_info ("protected-private-key passed to writekey\n");
|
||||
else if (toklen == 20 && !memcmp ("shadowed-private-key", tok, toklen))
|
||||
log_info ("shadowed-private-key passed to writekey\n");
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (!tok || toklen != 3 || memcmp ("rsa", tok, toklen))
|
||||
{
|
||||
err = gpg_error (GPG_ERR_WRONG_PUBKEY_ALGO);
|
||||
goto leave;
|
||||
}
|
||||
last_depth1 = depth;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
&& depth && depth >= last_depth1)
|
||||
{
|
||||
if (tok)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
goto leave;
|
||||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (tok && toklen == 1)
|
||||
{
|
||||
const unsigned char **mpi;
|
||||
size_t *mpi_len;
|
||||
|
||||
switch (*tok)
|
||||
{
|
||||
case 'n': mpi = &rsa_n; mpi_len = &rsa_n_len; break;
|
||||
case 'e': mpi = &rsa_e; mpi_len = &rsa_e_len; break;
|
||||
case 'p': mpi = &rsa_p; mpi_len = &rsa_p_len; break;
|
||||
case 'q': mpi = &rsa_q; mpi_len = &rsa_q_len;break;
|
||||
default: mpi = NULL; mpi_len = NULL; break;
|
||||
}
|
||||
if (mpi && *mpi)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_DUP_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (tok && mpi)
|
||||
{
|
||||
/* Strip off leading zero bytes and save. */
|
||||
for (;toklen && !*tok; toklen--, tok++)
|
||||
;
|
||||
*mpi = tok;
|
||||
*mpi_len = toklen;
|
||||
}
|
||||
}
|
||||
/* Skip until end of list. */
|
||||
last_depth2 = depth;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
&& depth && depth >= last_depth2)
|
||||
;
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
/* Parse other attributes. */
|
||||
last_depth1 = depth;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
&& depth && depth >= last_depth1)
|
||||
{
|
||||
if (tok)
|
||||
{
|
||||
err = gpg_error (GPG_ERR_UNKNOWN_SEXP);
|
||||
goto leave;
|
||||
}
|
||||
if ((err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen)))
|
||||
goto leave;
|
||||
if (tok && toklen == 10 && !memcmp ("created-at", tok, toklen))
|
||||
{
|
||||
if ((err = parse_sexp (&buf,&buflen,&depth,&tok,&toklen)))
|
||||
goto leave;
|
||||
if (tok)
|
||||
{
|
||||
for (created_at=0; toklen && *tok && *tok >= '0' && *tok <= '9';
|
||||
tok++, toklen--)
|
||||
created_at = created_at*10 + (*tok - '0');
|
||||
}
|
||||
}
|
||||
/* Skip until end of list. */
|
||||
last_depth2 = depth;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
&& depth && depth >= last_depth2)
|
||||
;
|
||||
if (err)
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
/* Check that we have all parameters and that they match the card
|
||||
description. */
|
||||
if (!created_at)
|
||||
{
|
||||
log_error (_("creation timestamp missing\n"));
|
||||
err = gpg_error (GPG_ERR_INV_VALUE);
|
||||
goto leave;
|
||||
}
|
||||
nbits = rsa_n? count_bits (rsa_n, rsa_n_len) : 0;
|
||||
if (nbits != 1024)
|
||||
{
|
||||
log_error (_("RSA modulus missing or not of size %d bits\n"), 1024);
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
nbits = rsa_e? count_bits (rsa_e, rsa_e_len) : 0;
|
||||
if (nbits < 2 || nbits > 32)
|
||||
{
|
||||
log_error (_("RSA public exponent missing or largerr than %d bits\n"),
|
||||
32);
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
nbits = rsa_p? count_bits (rsa_p, rsa_p_len) : 0;
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("RSA prime %s missing or not of size %d bits\n"), "P", 512);
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
nbits = rsa_q? count_bits (rsa_q, rsa_q_len) : 0;
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("RSA prime %s missing or not of size %d bits\n"), "Q", 512);
|
||||
err = gpg_error (GPG_ERR_BAD_SECKEY);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
|
||||
/* Build the private key template as described in section 4.3.3.6 of
|
||||
the OpenPGP card specs:
|
||||
0xC0 <length> public exponent
|
||||
0xC1 <length> prime p
|
||||
0xC2 <length> prime q
|
||||
*/
|
||||
assert (rsa_e_len <= 4);
|
||||
template_len = (1 + 1 + 4
|
||||
+ 1 + 1 + rsa_p_len
|
||||
+ 1 + 1 + rsa_q_len);
|
||||
template = tp = xtrymalloc_secure (template_len);
|
||||
if (!template)
|
||||
{
|
||||
err = gpg_error_from_errno (errno);
|
||||
goto leave;
|
||||
}
|
||||
*tp++ = 0xC0;
|
||||
*tp++ = 4;
|
||||
memcpy (tp, rsa_e, rsa_e_len);
|
||||
if (rsa_e_len < 4)
|
||||
{
|
||||
/* Right justify E. */
|
||||
memmove (tp+4-rsa_e_len, tp, 4-rsa_e_len);
|
||||
memset (tp, 0, 4-rsa_e_len);
|
||||
}
|
||||
tp += 4;
|
||||
|
||||
*tp++ = 0xC1;
|
||||
*tp++ = rsa_p_len;
|
||||
memcpy (tp, rsa_p, rsa_p_len);
|
||||
tp += rsa_p_len;
|
||||
|
||||
*tp++ = 0xC2;
|
||||
*tp++ = rsa_q_len;
|
||||
memcpy (tp, rsa_q, rsa_q_len);
|
||||
tp += rsa_q_len;
|
||||
|
||||
assert (tp - template == template_len);
|
||||
|
||||
|
||||
/* Obviously we need to remove the cached public key. */
|
||||
xfree (app->app_local->pk[keyno].key);
|
||||
app->app_local->pk[keyno].key = NULL;
|
||||
app->app_local->pk[keyno].keylen = 0;
|
||||
app->app_local->pk[keyno].read_done = 0;
|
||||
|
||||
/* Prepare for storing the key. */
|
||||
err = verify_chv3 (app, pincb, pincb_arg);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
/* Store the key. */
|
||||
err = iso7816_put_data (app->slot,
|
||||
(app->card_version > 0x0007? 0xE0 : 0xE9) + keyno,
|
||||
template, template_len);
|
||||
if (err)
|
||||
{
|
||||
log_error (_("failed to store the key: %s\n"), gpg_strerror (err));
|
||||
goto leave;
|
||||
}
|
||||
|
||||
err = store_fpr (app->slot, keyno, created_at,
|
||||
rsa_n, rsa_n_len, rsa_e, rsa_e_len,
|
||||
fprbuf, app->card_version);
|
||||
if (err)
|
||||
goto leave;
|
||||
|
||||
|
||||
leave:
|
||||
xfree (template);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
/* Handle the GENKEY command. */
|
||||
static gpg_error_t
|
||||
@ -1535,13 +1847,11 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||
void *pincb_arg)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
char numbuf[30];
|
||||
unsigned char fprbuf[20];
|
||||
const unsigned char *fpr;
|
||||
const unsigned char *keydata, *m, *e;
|
||||
unsigned char *buffer;
|
||||
size_t buflen, keydatalen, n, mlen, elen;
|
||||
unsigned char *buffer = NULL;
|
||||
size_t buflen, keydatalen, mlen, elen;
|
||||
time_t created_at;
|
||||
int keyno = atoi (keynostr);
|
||||
int force = (flags & 1);
|
||||
@ -1562,41 +1872,15 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
|
||||
app->app_local->pk[keyno].read_done = 0;
|
||||
|
||||
/* Check whether a key already exists. */
|
||||
rc = iso7816_get_data (app->slot, 0x006E, &buffer, &buflen);
|
||||
rc = does_key_exist (app, keyno, force);
|
||||
if (rc)
|
||||
{
|
||||
log_error (_("error reading application data\n"));
|
||||
return gpg_error (GPG_ERR_GENERAL);
|
||||
}
|
||||
fpr = find_tlv (buffer, buflen, 0x00C5, &n);
|
||||
if (!fpr || n != 60)
|
||||
{
|
||||
rc = gpg_error (GPG_ERR_GENERAL);
|
||||
log_error (_("error reading fingerprint DO\n"));
|
||||
goto leave;
|
||||
}
|
||||
fpr += 20*keyno;
|
||||
for (i=0; i < 20 && !fpr[i]; i++)
|
||||
;
|
||||
if (i!=20 && !force)
|
||||
{
|
||||
rc = gpg_error (GPG_ERR_EEXIST);
|
||||
log_error (_("key already exists\n"));
|
||||
goto leave;
|
||||
}
|
||||
else if (i!=20)
|
||||
log_info (_("existing key will be replaced\n"));
|
||||
else
|
||||
log_info (_("generating new key\n"));
|
||||
|
||||
return rc;
|
||||
|
||||
/* Prepare for key generation by verifying the ADmin PIN. */
|
||||
rc = verify_chv3 (app, pincb, pincb_arg);
|
||||
if (rc)
|
||||
goto leave;
|
||||
|
||||
xfree (buffer); buffer = NULL;
|
||||
|
||||
#if 1
|
||||
log_info (_("please wait while key is being generated ...\n"));
|
||||
start_at = time (NULL);
|
||||
@ -2220,6 +2504,7 @@ app_select_openpgp (app_t app)
|
||||
app->fnc.readkey = do_readkey;
|
||||
app->fnc.getattr = do_getattr;
|
||||
app->fnc.setattr = do_setattr;
|
||||
app->fnc.writekey = do_writekey;
|
||||
app->fnc.genkey = do_genkey;
|
||||
app->fnc.sign = do_sign;
|
||||
app->fnc.auth = do_auth;
|
||||
|
@ -63,6 +63,15 @@ struct pincb_parm_s
|
||||
};
|
||||
|
||||
|
||||
struct writekey_parm_s
|
||||
{
|
||||
assuan_context_t ctx;
|
||||
const unsigned char *keydata;
|
||||
size_t keydatalen;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static char *default_reader_port;
|
||||
static app_t current_app;
|
||||
|
||||
@ -100,7 +109,7 @@ serialno_and_fpr_from_sk (const unsigned char *sn, size_t snlen,
|
||||
buffers. The variable elements are pairs of (char *, size_t),
|
||||
terminated with a (NULL, 0). */
|
||||
void
|
||||
send_status_info (CTRL ctrl, const char *keyword, ...)
|
||||
send_status_info (ctrl_t ctrl, const char *keyword, ...)
|
||||
{
|
||||
va_list arg_ptr;
|
||||
const unsigned char *value;
|
||||
@ -140,6 +149,7 @@ send_status_info (CTRL ctrl, const char *keyword, ...)
|
||||
}
|
||||
}
|
||||
*p = 0;
|
||||
if (ctrl && ctrl->status_cb)
|
||||
ctrl->status_cb (ctrl->status_cb_arg, buf);
|
||||
|
||||
va_end (arg_ptr);
|
||||
@ -970,6 +980,59 @@ agent_scd_setattr (const char *name,
|
||||
}
|
||||
|
||||
|
||||
/* Handle a KEYDATA inquiry. Note, we only send the data,
|
||||
assuan_transact takes care of flushing and writing the end */
|
||||
static assuan_error_t
|
||||
inq_writekey_parms (void *opaque, const char *keyword)
|
||||
{
|
||||
struct writekey_parm_s *parm = opaque;
|
||||
|
||||
return assuan_send_data (parm->ctx, parm->keydata, parm->keydatalen);
|
||||
}
|
||||
|
||||
|
||||
/* Send a WRITEKEY command to the SCdaemon. */
|
||||
int
|
||||
agent_scd_writekey (int keyno, const unsigned char *keydata, size_t keydatalen)
|
||||
{
|
||||
app_t app;
|
||||
int rc;
|
||||
char line[ASSUAN_LINELENGTH];
|
||||
app = current_app? current_app : open_card ();
|
||||
if (!app)
|
||||
return gpg_error (GPG_ERR_CARD);
|
||||
|
||||
if (app->assuan_ctx)
|
||||
{
|
||||
struct writekey_parm_s parms;
|
||||
|
||||
snprintf (line, DIM(line)-1, "SCD WRITEKEY --force OPENPGP.%d", keyno);
|
||||
line[DIM(line)-1] = 0;
|
||||
parms.ctx = app->assuan_ctx;
|
||||
parms.keydata = keydata;
|
||||
parms.keydatalen = keydatalen;
|
||||
rc = test_transact (assuan_transact (app->assuan_ctx, line,
|
||||
NULL, NULL,
|
||||
inq_writekey_parms, &parms,
|
||||
NULL, NULL),
|
||||
"SCD WRITEKEY");
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (line, DIM(line)-1, "OPENPGP.%d", keyno);
|
||||
line[DIM(line)-1] = 0;
|
||||
rc = app->fnc.writekey (app, NULL, line, 0x0001,
|
||||
pin_cb, NULL,
|
||||
keydata, keydatalen);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
write_status (STATUS_SC_OP_FAILURE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static assuan_error_t
|
||||
genkey_status_cb (void *opaque, const char *line)
|
||||
{
|
||||
@ -1281,37 +1344,6 @@ agent_scd_checkpin (const char *serialnobuf)
|
||||
}
|
||||
|
||||
|
||||
/* Wrapper to call the store key helper function of app-openpgp.c. */
|
||||
int
|
||||
agent_openpgp_storekey (int keyno,
|
||||
unsigned char *template, size_t template_len,
|
||||
time_t created_at,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const unsigned char *e, size_t elen)
|
||||
{
|
||||
app_t app;
|
||||
int rc;
|
||||
|
||||
app = current_app? current_app : open_card ();
|
||||
if (!app)
|
||||
return gpg_error (GPG_ERR_CARD);
|
||||
|
||||
if (app->assuan_ctx)
|
||||
{
|
||||
rc = gpg_error (GPG_ERR_CARD);
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = app_openpgp_storekey (app, keyno, template, template_len,
|
||||
created_at, m, mlen, e, elen,
|
||||
pin_cb, NULL);
|
||||
}
|
||||
|
||||
if (rc)
|
||||
write_status (STATUS_SC_OP_FAILURE);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
agent_clear_pin_cache (const char *sn)
|
||||
|
@ -81,6 +81,7 @@ typedef struct ctrl_ctx_s *ctrl_t;
|
||||
|
||||
#define GPG_ERR_GENERAL G10ERR_GENERAL
|
||||
#define GPG_ERR_BAD_PIN G10ERR_BAD_PASS
|
||||
#define GPG_ERR_BAD_KEy G10ERR_BAD_KEY
|
||||
#define GPG_ERR_CARD G10ERR_GENERAL
|
||||
#define GPG_ERR_EEXIST G10ERR_FILE_EXISTS
|
||||
#define GPG_ERR_ENOMEM G10ERR_RESOURCE_LIMIT
|
||||
@ -105,6 +106,10 @@ typedef struct ctrl_ctx_s *ctrl_t;
|
||||
#define GPG_ERR_EOF (-1)
|
||||
#define GPG_ERR_CARD_NOT_PRESENT G10ERR_NO_CARD
|
||||
#define GPG_ERR_CARD_RESET G10ERR_GENERAL
|
||||
#define GPG_ERR_WRONG_PUBKEY_ALGO G10ERR_PUBKEY_ALGO
|
||||
#define GPG_ERR_UNKNOWN_SEXP G10ERR_INV_ARG
|
||||
#define GPG_ERR_DUP_VALUE G10ERR_INV_ARG
|
||||
#define GPG_ERR_BAD_SECKEY G10ERR_BAD_SECKEY
|
||||
|
||||
#define GPG_ERR_EBUSY G10ERR_GENERAL
|
||||
#define GPG_ERR_ENOENT G10ERR_OPEN_FILE
|
||||
@ -129,6 +134,7 @@ typedef int gpg_err_code_t;
|
||||
#define xtrymalloc(n) xmalloc((n))
|
||||
#define xtrycalloc(n,m) xcalloc((n),(m))
|
||||
#define xtryrealloc(n,m) xrealloc((n),(m))
|
||||
#define xtrymalloc_secure(n) xmalloc_secure((n))
|
||||
#define out_of_core() (-1)
|
||||
|
||||
#define gnupg_get_time() make_timestamp ()
|
||||
@ -168,6 +174,10 @@ int agent_scd_getattr (const char *name, struct agent_card_info_s *info);
|
||||
int agent_scd_setattr (const char *name,
|
||||
const unsigned char *value, size_t valuelen);
|
||||
|
||||
/* Send a WRITEKEY command to the SCdaemon. */
|
||||
int agent_scd_writekey (int keyno,
|
||||
const unsigned char *keydata, size_t keydatalen);
|
||||
|
||||
/* Send a GENKEY command to the SCdaemon. */
|
||||
int agent_scd_genkey (struct agent_card_genkey_s *info, int keyno, int force);
|
||||
|
||||
@ -187,13 +197,6 @@ int agent_scd_change_pin (int chvno);
|
||||
/* Send a CHECKPIN command. */
|
||||
int agent_scd_checkpin (const char *serialnobuf);
|
||||
|
||||
/* Call the store key utility command. */
|
||||
int agent_openpgp_storekey (int keyno,
|
||||
unsigned char *template, size_t template_len,
|
||||
time_t created_at,
|
||||
const unsigned char *m, size_t mlen,
|
||||
const unsigned char *e, size_t elen);
|
||||
|
||||
/* Clear a cached PIN. */
|
||||
void agent_clear_pin_cache (const char *sn);
|
||||
|
||||
|
166
g10/keygen.c
166
g10/keygen.c
@ -128,42 +128,6 @@ static int gen_card_key_with_backup (int algo, int keyno, int is_primary,
|
||||
const char *backup_dir);
|
||||
|
||||
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
#define GET_NBITS(a) mpi_get_nbits (a)
|
||||
#else
|
||||
#define GET_NBITS(a) gcry_mpi_get_nbits (a)
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_CARD_SUPPORT
|
||||
static int
|
||||
copy_mpi (MPI a, unsigned char *buffer, size_t len, size_t *ncopied)
|
||||
{
|
||||
int rc;
|
||||
#if GNUPG_MAJOR_VERSION == 1
|
||||
unsigned char *tmp;
|
||||
unsigned int n;
|
||||
|
||||
tmp = mpi_get_secure_buffer (a, &n, NULL);
|
||||
if (n > len)
|
||||
rc = G10ERR_GENERAL;
|
||||
else
|
||||
{
|
||||
rc = 0;
|
||||
memcpy (buffer, tmp, n);
|
||||
*ncopied = n;
|
||||
}
|
||||
xfree (tmp);
|
||||
#else /* GNUPG_MAJOR_VERSION != 1 */
|
||||
rc = gcry_mpi_print (GCRYMPI_FMT_USG, buffer, len, ncopied, a);
|
||||
#endif /* GNUPG_MAJOR_VERSION != 1 */
|
||||
if (rc)
|
||||
log_error ("mpi_copy failed: %s\n", gpg_strerror (rc));
|
||||
return rc;
|
||||
}
|
||||
#endif /* ENABLE_CARD_SUPPORT */
|
||||
|
||||
|
||||
|
||||
static void
|
||||
print_status_key_created (int letter, PKT_public_key *pk, const char *handle)
|
||||
{
|
||||
@ -3527,104 +3491,68 @@ int
|
||||
save_unprotected_key_to_card (PKT_secret_key *sk, int keyno)
|
||||
{
|
||||
int rc;
|
||||
size_t n;
|
||||
MPI rsa_n, rsa_e, rsa_p, rsa_q;
|
||||
unsigned int nbits;
|
||||
unsigned char *template = NULL;
|
||||
unsigned char *tp;
|
||||
unsigned char m[128], e[4];
|
||||
size_t mlen, elen;
|
||||
unsigned char *rsa_n = NULL;
|
||||
unsigned char *rsa_e = NULL;
|
||||
unsigned char *rsa_p = NULL;
|
||||
unsigned char *rsa_q = NULL;
|
||||
unsigned int rsa_n_len, rsa_e_len, rsa_p_len, rsa_q_len;
|
||||
unsigned char *sexp = NULL;
|
||||
unsigned char *p;
|
||||
char numbuf[55], numbuf2[50];
|
||||
|
||||
assert (is_RSA (sk->pubkey_algo));
|
||||
assert (!sk->is_protected);
|
||||
|
||||
rc = -1;
|
||||
/* Some basic checks on the key parameters. */
|
||||
rsa_n = sk->skey[0];
|
||||
rsa_e = sk->skey[1];
|
||||
rsa_p = sk->skey[3];
|
||||
rsa_q = sk->skey[4];
|
||||
|
||||
nbits = GET_NBITS (rsa_n);
|
||||
if (nbits != 1024)
|
||||
/* Copy the parameters into straight buffers. */
|
||||
rsa_n = mpi_get_secure_buffer (sk->skey[0], &rsa_n_len, NULL);
|
||||
rsa_e = mpi_get_secure_buffer (sk->skey[1], &rsa_e_len, NULL);
|
||||
rsa_p = mpi_get_secure_buffer (sk->skey[3], &rsa_p_len, NULL);
|
||||
rsa_q = mpi_get_secure_buffer (sk->skey[4], &rsa_q_len, NULL);
|
||||
if (!rsa_n || !rsa_e || !rsa_p || !rsa_q)
|
||||
{
|
||||
log_error (_("length of RSA modulus is not %d\n"), 1024);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_e);
|
||||
if (nbits < 2 || nbits > 32)
|
||||
{
|
||||
log_error (_("public exponent too large (more than 32 bits)\n"));
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_p);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
goto leave;
|
||||
}
|
||||
nbits = GET_NBITS (rsa_q);
|
||||
if (nbits != 512)
|
||||
{
|
||||
log_error (_("length of an RSA prime is not %d\n"), 512);
|
||||
rc = G10ERR_INV_ARG;
|
||||
goto leave;
|
||||
}
|
||||
|
||||
/* Put the key into an S-expression. */
|
||||
sexp = p = xmalloc_secure (30
|
||||
+ rsa_n_len + rsa_e_len + rsa_p_len + rsa_q_len
|
||||
+ 4*sizeof (numbuf) + 25 + sizeof(numbuf) + 20);
|
||||
|
||||
/* We need the modulus later to calculate the fingerprint. */
|
||||
rc = copy_mpi (rsa_n, m, 128, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 128);
|
||||
mlen = 128;
|
||||
p = stpcpy (p,"(11:private-key(3:rsa(1:n");
|
||||
sprintf (numbuf, "%u:", rsa_n_len);
|
||||
p = stpcpy (p, numbuf);
|
||||
memcpy (p, rsa_n, rsa_n_len);
|
||||
p += rsa_n_len;
|
||||
|
||||
/* Build the private key template as described in section 4.3.3.6 of
|
||||
the OpenPGP card specs:
|
||||
0xC0 <length> public exponent
|
||||
0xC1 <length> prime p
|
||||
0xC2 <length> prime q
|
||||
*/
|
||||
template = tp = xmalloc_secure (1+2 + 1+1+4 + 1+1+(512/8) + 1+1+(512/8));
|
||||
*tp++ = 0xC0;
|
||||
*tp++ = 4;
|
||||
rc = copy_mpi (rsa_e, tp, 4, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n <= 4);
|
||||
memcpy (e, tp, n); /* Save a copy of the exponent for later use. */
|
||||
elen = n;
|
||||
if (n != 4)
|
||||
{
|
||||
memmove (tp+4-n, tp, 4-n);
|
||||
memset (tp, 0, 4-n);
|
||||
}
|
||||
tp += 4;
|
||||
sprintf (numbuf, ")(1:e%u:", rsa_e_len);
|
||||
p = stpcpy (p, numbuf);
|
||||
memcpy (p, rsa_e, rsa_e_len);
|
||||
p += rsa_e_len;
|
||||
|
||||
*tp++ = 0xC1;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_p, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
sprintf (numbuf, ")(1:p%u:", rsa_p_len);
|
||||
p = stpcpy (p, numbuf);
|
||||
memcpy (p, rsa_p, rsa_p_len);
|
||||
p += rsa_p_len;
|
||||
|
||||
*tp++ = 0xC2;
|
||||
*tp++ = 64;
|
||||
rc = copy_mpi (rsa_q, tp, 64, &n);
|
||||
if (rc)
|
||||
goto leave;
|
||||
assert (n == 64);
|
||||
tp += 64;
|
||||
assert (tp - template == 138);
|
||||
sprintf (numbuf, ")(1:q%u:", rsa_q_len);
|
||||
p = stpcpy (p, numbuf);
|
||||
memcpy (p, rsa_q, rsa_q_len);
|
||||
p += rsa_q_len;
|
||||
|
||||
rc = agent_openpgp_storekey (keyno,
|
||||
template, tp - template,
|
||||
sk->timestamp,
|
||||
m, mlen,
|
||||
e, elen);
|
||||
p = stpcpy (p,"))(10:created-at");
|
||||
sprintf (numbuf2, "%lu", (unsigned long)sk->timestamp);
|
||||
sprintf (numbuf, "%d:", strlen (numbuf2));
|
||||
p = stpcpy (stpcpy (stpcpy (p, numbuf), numbuf2), "))");
|
||||
|
||||
rc = agent_scd_writekey (keyno, sexp, p - sexp);
|
||||
|
||||
leave:
|
||||
xfree (template);
|
||||
xfree (sexp);
|
||||
xfree (rsa_n);
|
||||
xfree (rsa_e);
|
||||
xfree (rsa_p);
|
||||
xfree (rsa_q);
|
||||
return rc;
|
||||
}
|
||||
#endif /*ENABLE_CARD_SUPPORT*/
|
||||
|
73
g10/tlv.c
73
g10/tlv.c
@ -221,3 +221,76 @@ parse_ber_header (unsigned char const **buffer, size_t *size,
|
||||
*size = length;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* FIXME: The following function should not go into this file but for
|
||||
now it is easier to keep it here. */
|
||||
|
||||
/* Return the next token of an canconical encoded S-expression. BUF
|
||||
is the pointer to the S-expression and BUFLEN is a pointer to the
|
||||
length of this S-expression (used to validate the syntax). Both
|
||||
are updated to reflect the new position. The token itself is
|
||||
returned as a pointer into the orginal buffer at TOK and TOKLEN.
|
||||
If a parentheses is the next token, TOK will be set to NULL.
|
||||
TOKLEN is checked to be within the bounds. On error a error code
|
||||
is returned and all pointers should are not guaranteed to point to
|
||||
a meanigful value. DEPTH should be initialized to 0 and will
|
||||
reflect on return the actual depth of the tree. To detect the end
|
||||
of the S-expression it is advisable to check DEPTH after a
|
||||
successful return:
|
||||
|
||||
depth = 0;
|
||||
while (!(err = parse_sexp (&buf, &buflen, &depth, &tok, &toklen))
|
||||
&& depth)
|
||||
process_token (tok, toklen);
|
||||
if (err)
|
||||
handle_error ();
|
||||
*/
|
||||
gpg_error_t
|
||||
parse_sexp (unsigned char const **buf, size_t *buflen,
|
||||
int *depth, unsigned char const **tok, size_t *toklen)
|
||||
{
|
||||
const unsigned char *s;
|
||||
size_t n, vlen;
|
||||
|
||||
s = *buf;
|
||||
n = *buflen;
|
||||
*tok = NULL;
|
||||
*toklen = 0;
|
||||
if (!n)
|
||||
return *depth ? gpg_error (GPG_ERR_INV_SEXP) : 0;
|
||||
if (*s == '(')
|
||||
{
|
||||
s++; n--;
|
||||
(*depth)++;
|
||||
*buf = s;
|
||||
*buflen = n;
|
||||
return 0;
|
||||
}
|
||||
if (*s == ')')
|
||||
{
|
||||
if (!*depth)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
*toklen = 1;
|
||||
s++; n--;
|
||||
(*depth)--;
|
||||
*buf = s;
|
||||
*buflen = n;
|
||||
return 0;
|
||||
}
|
||||
for (vlen=0; n && *s && *s != ':' && (*s >= '0' && *s <= '9'); s++, n--)
|
||||
vlen = vlen*10 + (*s - '0');
|
||||
if (!n || *s != ':')
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
s++; n--;
|
||||
if (vlen > n)
|
||||
return gpg_error (GPG_ERR_INV_SEXP);
|
||||
*tok = s;
|
||||
*toklen = vlen;
|
||||
s += vlen;
|
||||
n -= vlen;
|
||||
*buf = s;
|
||||
*buflen = n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
17
g10/tlv.h
17
g10/tlv.h
@ -88,4 +88,21 @@ gpg_error_t parse_ber_header (unsigned char const **buffer, size_t *size,
|
||||
|
||||
|
||||
|
||||
/* Return the next token of an canconical encoded S-expression. BUF
|
||||
is the pointer to the S-expression and BUFLEN is a pointer to the
|
||||
length of this S-expression (used to validate the syntax). Both
|
||||
are updated to reflect the new position. The token itself is
|
||||
returned as a pointer into the orginal buffer at TOK and TOKLEN.
|
||||
If a parentheses is the next token, TOK will be set to NULL.
|
||||
TOKLEN is checked to be within the bounds. On error a error code
|
||||
is returned and all pointers should are not guaranteed to point to
|
||||
a meanigful value. DEPTH should be initialized to 0 and will
|
||||
reflect on return the actual depth of the tree. To detect the end
|
||||
of the S-expression it is advisable to check DEPTH after a
|
||||
successful return. */
|
||||
gpg_error_t parse_sexp (unsigned char const **buf, size_t *buflen,
|
||||
int *depth, unsigned char const **tok, size_t *toklen);
|
||||
|
||||
|
||||
|
||||
#endif /* SCD_TLV_H */
|
||||
|
@ -1,3 +1,7 @@
|
||||
2005-05-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* util.h: Add definitions for membuf functions.
|
||||
|
||||
2005-05-05 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* util.h: Remove add_days_to_timestamp as unused.
|
||||
|
@ -222,6 +222,24 @@ int strncasecmp (const char *, const char *b, size_t n);
|
||||
#define memmove(d, s, n) bcopy((s), (d), (n))
|
||||
#endif
|
||||
|
||||
/*-- membuf.c --*/
|
||||
/* The definition of the structure is private, we only need it here,
|
||||
so it can be allocated on the stack. */
|
||||
struct private_membuf_s {
|
||||
size_t len;
|
||||
size_t size;
|
||||
char *buf;
|
||||
int out_of_core;
|
||||
};
|
||||
|
||||
typedef struct private_membuf_s membuf_t;
|
||||
|
||||
void init_membuf (membuf_t *mb, int initiallen);
|
||||
void put_membuf (membuf_t *mb, const void *buf, size_t len);
|
||||
void *get_membuf (membuf_t *mb, size_t *len);
|
||||
|
||||
|
||||
|
||||
#if defined (_WIN32)
|
||||
/*-- w32reg.c --*/
|
||||
char *read_w32_registry_string( const char *root,
|
||||
@ -232,7 +250,8 @@ int write_w32_registry_string(const char *root, const char *dir,
|
||||
/*-- strgutil.c --*/
|
||||
int vasprintf (char **result, const char *format, va_list args);
|
||||
int asprintf (char **buf, const char *fmt, ...);
|
||||
#endif
|
||||
#endif /*_WIN32*/
|
||||
|
||||
|
||||
/**** other missing stuff ****/
|
||||
#ifndef HAVE_ATEXIT /* For SunOS */
|
||||
|
@ -57,7 +57,7 @@ X.509 specific are noted like [X.509: xxx]
|
||||
b20 The keys fingerprint
|
||||
(fingerprints are always 20 bytes, MD5 left padded with zeroes)
|
||||
u32 offset to the n-th key's keyID (a keyID is always 8 byte)
|
||||
or 0 if not known which is the case opnly for X509.
|
||||
or 0 if not known which is the case only for X509.
|
||||
u16 special key flags
|
||||
bit 0 =
|
||||
u16 reserved
|
||||
@ -72,7 +72,7 @@ X.509 specific are noted like [X.509: xxx]
|
||||
bit 0 =
|
||||
byte validity
|
||||
byte reserved
|
||||
[For X509, the first user ID is the ISsuer, the second the subject
|
||||
[For X509, the first user ID is the issuer, the second the subject
|
||||
and the others are subjectAltNames]
|
||||
u16 number of signatures
|
||||
u16 size of signature information (4)
|
||||
@ -99,7 +99,7 @@ X.509 specific are noted like [X.509: xxx]
|
||||
|
||||
b16 MD5 checksum (useful for KS syncronisation), we might also want to use
|
||||
a mac here.
|
||||
b4 resevered
|
||||
b4 reserved
|
||||
|
||||
*/
|
||||
|
||||
|
@ -1,3 +1,12 @@
|
||||
2005-05-06 Werner Koch <wk@g10code.com>
|
||||
|
||||
* mpi-scan.c (mpi_putbyte, mpi_getbyte): Removed. Not used.
|
||||
|
||||
2005-04-21 Werner Koch <wk@g10code.com>
|
||||
|
||||
* mpicoder.c (mpi_read): Changed error detection to always return
|
||||
an error while maintaining the actual number of bytes read.
|
||||
|
||||
2005-03-11 Werner Koch <wk@g10code.com>
|
||||
|
||||
* Makefile.am (ASFLAGS): Renamed to AM_CCASFLAGS and added the
|
||||
|
@ -31,6 +31,7 @@
|
||||
*
|
||||
* FIXME: This code is VERY ugly!
|
||||
*/
|
||||
#if 0 /* Code is not used */
|
||||
int
|
||||
mpi_getbyte( MPI a, unsigned idx )
|
||||
{
|
||||
@ -48,14 +49,19 @@ mpi_getbyte( MPI a, unsigned idx )
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
#endif /* Code is not used */
|
||||
|
||||
|
||||
/****************
|
||||
* Put a value at position IDX into A. idx counts from lsb to msb
|
||||
*/
|
||||
/* FIXME: There is a problem with the long constants which should have
|
||||
a LL prefix or better the macros we use at other places. */
|
||||
#if 0 /* Code is not used */
|
||||
void
|
||||
mpi_putbyte( MPI a, unsigned idx, int xc )
|
||||
{
|
||||
|
||||
int i, j;
|
||||
unsigned n;
|
||||
mpi_ptr_t ap;
|
||||
@ -104,12 +110,13 @@ mpi_putbyte( MPI a, unsigned idx, int xc )
|
||||
}
|
||||
abort(); /* index out of range */
|
||||
}
|
||||
#endif /* Code is not used */
|
||||
|
||||
|
||||
/****************
|
||||
* Count the number of zerobits at the low end of A
|
||||
*/
|
||||
unsigned
|
||||
unsigned int
|
||||
mpi_trailing_zeros( MPI a )
|
||||
{
|
||||
unsigned n, count = 0;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* mpicoder.c - Coder for the external representation of MPIs
|
||||
* Copyright (C) 1998, 1999 Free Software Foundation, Inc.
|
||||
* Copyright (C) 1998, 1999, 2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -74,20 +74,23 @@ mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
|
||||
#endif
|
||||
{
|
||||
int c, i, j;
|
||||
unsigned int nmax = *ret_nread;
|
||||
unsigned nbits, nbytes, nlimbs, nread=0;
|
||||
mpi_limb_t a;
|
||||
MPI val = MPI_NULL;
|
||||
|
||||
if( (c = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nread++;
|
||||
if (++nread >= nmax)
|
||||
goto overflow;
|
||||
nbits = c << 8;
|
||||
if( (c = iobuf_get(inp)) == -1 )
|
||||
goto leave;
|
||||
nread++;
|
||||
if (++nread >= nmax)
|
||||
goto overflow;
|
||||
nbits |= c;
|
||||
if( nbits > MAX_EXTERN_MPI_BITS ) {
|
||||
log_error("mpi too large (%u bits)\n", nbits);
|
||||
log_error("mpi too large for this implementation (%u bits)\n", nbits);
|
||||
goto leave;
|
||||
}
|
||||
|
||||
@ -108,6 +111,15 @@ mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
|
||||
for( ; j > 0; j-- ) {
|
||||
a = 0;
|
||||
for(; i < BYTES_PER_MPI_LIMB; i++ ) {
|
||||
if (nread >= nmax) {
|
||||
#ifdef M_DEBUG
|
||||
mpi_debug_free (val);
|
||||
#else
|
||||
mpi_free (val);
|
||||
#endif
|
||||
val = NULL;
|
||||
goto overflow;
|
||||
}
|
||||
a <<= 8;
|
||||
a |= iobuf_get(inp) & 0xff; nread++;
|
||||
}
|
||||
@ -116,9 +128,10 @@ mpi_read(IOBUF inp, unsigned *ret_nread, int secure)
|
||||
}
|
||||
|
||||
leave:
|
||||
if( nread > *ret_nread )
|
||||
log_bug("mpi crosses packet border\n");
|
||||
else
|
||||
*ret_nread = nread;
|
||||
return val;
|
||||
overflow:
|
||||
log_error ("mpi larger than indicated length (%u bytes)\n", nmax);
|
||||
*ret_nread = nread;
|
||||
return val;
|
||||
}
|
||||
|
@ -1,3 +1,7 @@
|
||||
2005-05-19 Werner Koch <wk@g10code.com>
|
||||
|
||||
* membuf.c: New. Taken from gnupg 1.9.
|
||||
|
||||
2005-05-05 David Shaw <dshaw@jabberwocky.com>
|
||||
|
||||
* miscutil.c (add_days_to_timestamp): Remove as unused.
|
||||
|
@ -39,7 +39,7 @@ endif
|
||||
libutil_a_SOURCES = logger.c fileutil.c miscutil.c strgutil.c \
|
||||
ttyio.c argparse.c memory.c secmem.c errors.c iobuf.c \
|
||||
dotlock.c http.c srv.h srv.c simple-gettext.c \
|
||||
w32reg.c $(assuan_source)
|
||||
membuf.c w32reg.c $(assuan_source)
|
||||
|
||||
libutil_a_DEPENDENCIES = @LIBOBJS@ @REGEX_O@
|
||||
# LIBOBJS is for the replacement functions
|
||||
|
83
util/membuf.c
Normal file
83
util/membuf.c
Normal file
@ -0,0 +1,83 @@
|
||||
/* membuf.c - A simple implementation of a dynamic buffer
|
||||
* Copyright (C) 2001, 2003 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
* GnuPG is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GnuPG is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/* A simple implementation of a dynamic buffer. Use init_membuf() to
|
||||
create a buffer, put_membuf to append bytes and get_membuf to
|
||||
release and return the buffer. Allocation errors are detected but
|
||||
only returned at the final get_membuf(), this helps not to clutter
|
||||
the code with out of core checks. */
|
||||
|
||||
void
|
||||
init_membuf (membuf_t *mb, int initiallen)
|
||||
{
|
||||
mb->len = 0;
|
||||
mb->size = initiallen;
|
||||
mb->out_of_core = 0;
|
||||
mb->buf = xmalloc (initiallen);
|
||||
if (!mb->buf)
|
||||
mb->out_of_core = errno;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
put_membuf (membuf_t *mb, const void *buf, size_t len)
|
||||
{
|
||||
if (mb->out_of_core)
|
||||
return;
|
||||
|
||||
if (mb->len + len >= mb->size)
|
||||
{
|
||||
char *p;
|
||||
|
||||
mb->size += len + 1024;
|
||||
p = xrealloc (mb->buf, mb->size);
|
||||
mb->buf = p;
|
||||
}
|
||||
memcpy (mb->buf + mb->len, buf, len);
|
||||
mb->len += len;
|
||||
}
|
||||
|
||||
|
||||
void *
|
||||
get_membuf (membuf_t *mb, size_t *len)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (mb->out_of_core)
|
||||
{
|
||||
xfree (mb->buf);
|
||||
mb->buf = NULL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
p = mb->buf;
|
||||
*len = mb->len;
|
||||
mb->buf = NULL;
|
||||
mb->out_of_core = ENOMEM; /* hack to make sure it won't get reused. */
|
||||
return p;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user