diff options
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c | 59 | ||||
-rw-r--r-- | src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c | 12 |
2 files changed, 51 insertions, 20 deletions
diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c index 611ab2467..0df9fdaef 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_private_key.c @@ -61,12 +61,14 @@ struct private_gcrypt_rsa_private_key_t { public_key_t *gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key); /** - * find a token in a S-expression + * find a token in a S-expression. If a key is given, its length is used to + * pad the output to a given length. */ -chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name) +chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key) { gcry_sexp_t token; - chunk_t data = chunk_empty; + chunk_t data = chunk_empty, tmp; + size_t len = 0; token = gcry_sexp_find_token(sexp, name, 1); if (token) @@ -76,7 +78,36 @@ chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name) { data.len = 0; } - data = chunk_clone(data); + else + { + if (key) + { + /* gcrypt might return more bytes than necessary. Truncate + * to key lenght if key given, or prepend zeros if needed */ + len = gcry_pk_get_nbits(key); + len = len / 8 + (len % 8 ? 1 : 0); + if (len > data.len) + { + tmp = chunk_alloc(len); + len -= data.len; + memset(tmp.ptr, 0, tmp.len - len); + memcpy(tmp.ptr + len, data.ptr, data.len); + data = tmp; + } + else if (len < data.len) + { + data = chunk_clone(chunk_skip(data, data.len - len)); + } + else + { + data = chunk_clone(data); + } + } + else + { + data = chunk_clone(data); + } + } gcry_sexp_release(token); } return data; @@ -124,7 +155,7 @@ static bool sign_raw(private_gcrypt_rsa_private_key_t *this, DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err)); return FALSE; } - *signature = gcrypt_rsa_find_token(out, "s"); + *signature = gcrypt_rsa_find_token(out, "s", this->key); gcry_sexp_release(out); return !!signature->len; } @@ -170,7 +201,7 @@ static bool sign_pkcs1(private_gcrypt_rsa_private_key_t *this, DBG1("creating pkcs1 signature failed: %s", gpg_strerror(err)); return FALSE; } - *signature = gcrypt_rsa_find_token(out, "s"); + *signature = gcrypt_rsa_find_token(out, "s", this->key); gcry_sexp_release(out); return !!signature->len; } @@ -353,9 +384,9 @@ static chunk_t get_encoding(private_gcrypt_rsa_private_key_t *this) gcry_error_t err; /* p and q are swapped, gcrypt expects p < q */ - cp = gcrypt_rsa_find_token(this->key, "q"); - cq = gcrypt_rsa_find_token(this->key, "p"); - cd = gcrypt_rsa_find_token(this->key, "d"); + cp = gcrypt_rsa_find_token(this->key, "q", NULL); + cq = gcrypt_rsa_find_token(this->key, "p", NULL); + cd = gcrypt_rsa_find_token(this->key, "d", NULL); err = gcry_mpi_scan(&p, GCRYMPI_FMT_USG, cp.ptr, cp.len, NULL) | gcry_mpi_scan(&q, GCRYMPI_FMT_USG, cq.ptr, cq.len, NULL) @@ -401,14 +432,14 @@ static chunk_t get_encoding(private_gcrypt_rsa_private_key_t *this) } return asn1_wrap(ASN1_SEQUENCE, "cmmmmmmmm", ASN1_INTEGER_0, - asn1_integer("m", gcrypt_rsa_find_token(this->key, "n")), - asn1_integer("m", gcrypt_rsa_find_token(this->key, "e")), + asn1_integer("m", gcrypt_rsa_find_token(this->key, "n", NULL)), + asn1_integer("m", gcrypt_rsa_find_token(this->key, "e", NULL)), asn1_integer("m", cd), asn1_integer("m", cp), asn1_integer("m", cq), asn1_integer("m", cexp1), asn1_integer("m", cexp2), - asn1_integer("m", gcrypt_rsa_find_token(this->key, "u"))); + asn1_integer("m", gcrypt_rsa_find_token(this->key, "u", NULL))); } /** @@ -477,8 +508,8 @@ bool gcrypt_rsa_build_keyids(gcry_sexp_t key, identification_t **keyid, return FALSE; } publicKey = asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_integer("m", gcrypt_rsa_find_token(key, "n")), - asn1_integer("m", gcrypt_rsa_find_token(key, "e"))); + asn1_integer("m", gcrypt_rsa_find_token(key, "n", NULL)), + asn1_integer("m", gcrypt_rsa_find_token(key, "e", NULL))); hasher->allocate_hash(hasher, publicKey, &hash); *keyid = identification_create_from_encoding(ID_PUBKEY_SHA1, hash); chunk_free(&hash); diff --git a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c index 8024f58a7..f5e749dba 100644 --- a/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c +++ b/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c @@ -60,7 +60,7 @@ struct private_gcrypt_rsa_public_key_t { /** * Implemented in gcrypt_rsa_private_key.c */ -chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name); +chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key); bool gcrypt_rsa_build_keyids(gcry_sexp_t key, identification_t **keyid, identification_t **keyid_info); @@ -226,7 +226,7 @@ static bool encrypt_(private_gcrypt_rsa_public_key_t *this, chunk_t plain, DBG1("encrypting data using pkcs1 failed: %s", gpg_strerror(err)); return FALSE; } - *encrypted = gcrypt_rsa_find_token(out, "a"); + *encrypted = gcrypt_rsa_find_token(out, "a", this->key); gcry_sexp_release(out); return !!encrypted->len; } @@ -290,8 +290,8 @@ static identification_t *get_id(private_gcrypt_rsa_public_key_t *this, static chunk_t get_encoding(private_gcrypt_rsa_public_key_t *this) { return asn1_wrap(ASN1_SEQUENCE, "mm", - asn1_integer("m", gcrypt_rsa_find_token(this->key, "n")), - asn1_integer("m", gcrypt_rsa_find_token(this->key, "e"))); + asn1_integer("m", gcrypt_rsa_find_token(this->key, "n", NULL)), + asn1_integer("m", gcrypt_rsa_find_token(this->key, "e", NULL))); } /** @@ -352,8 +352,8 @@ public_key_t *gcrypt_rsa_public_key_create_from_sexp(gcry_sexp_t key) chunk_t n, e; this = gcrypt_rsa_public_key_create_empty(); - n = gcrypt_rsa_find_token(key, "n"); - e = gcrypt_rsa_find_token(key, "e"); + n = gcrypt_rsa_find_token(key, "n", NULL); + e = gcrypt_rsa_find_token(key, "e", NULL); err = gcry_sexp_build(&this->key, NULL, "(public-key(rsa(n %b)(e %b)))", n.len, n.ptr, e.len, e.ptr); |