Merge branch 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
* 'for-linus2' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: lib: Fix 32-bit sparc udiv_qrnnd() definition in mpilib's longlong.h lib: Fix multiple definitions of clz_tab lib/digsig: checks for NULL return value lib/mpi: added missing NULL check lib/mpi: added comment on divide by 0 case lib/mpi: check for possible zero length lib/digsig: pkcs_1_v1_5_decode_emsa cleanup lib/digsig: additional sanity checks against badly formated key payload lib/mpi: removed unused functions lib/mpi: checks for zero divisor length lib/mpi: return error code on dividing by zero lib/mpi: replaced MPI_NULL with normal NULL lib/mpi: added missing NULL check
This commit is contained in:
commit
ce106ad310
14 changed files with 98 additions and 167 deletions
|
@ -33,6 +33,7 @@ config SPARC
|
||||||
config SPARC32
|
config SPARC32
|
||||||
def_bool !64BIT
|
def_bool !64BIT
|
||||||
select GENERIC_ATOMIC64
|
select GENERIC_ATOMIC64
|
||||||
|
select CLZ_TAB
|
||||||
|
|
||||||
config SPARC64
|
config SPARC64
|
||||||
def_bool 64BIT
|
def_bool 64BIT
|
||||||
|
|
|
@ -17,23 +17,9 @@ along with GNU CC; see the file COPYING. If not, write to
|
||||||
the Free Software Foundation, 59 Temple Place - Suite 330,
|
the Free Software Foundation, 59 Temple Place - Suite 330,
|
||||||
Boston, MA 02111-1307, USA. */
|
Boston, MA 02111-1307, USA. */
|
||||||
|
|
||||||
.data
|
|
||||||
.align 8
|
|
||||||
.globl __clz_tab
|
|
||||||
__clz_tab:
|
|
||||||
.byte 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5
|
|
||||||
.byte 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6
|
|
||||||
.byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
|
|
||||||
.byte 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
|
|
||||||
.byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
|
||||||
.byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
|
||||||
.byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
|
||||||
.byte 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8
|
|
||||||
.size __clz_tab,256
|
|
||||||
.global .udiv
|
|
||||||
|
|
||||||
.text
|
.text
|
||||||
.align 4
|
.align 4
|
||||||
|
.global .udiv
|
||||||
.globl __divdi3
|
.globl __divdi3
|
||||||
__divdi3:
|
__divdi3:
|
||||||
save %sp,-104,%sp
|
save %sp,-104,%sp
|
||||||
|
|
|
@ -57,8 +57,6 @@ struct gcry_mpi {
|
||||||
|
|
||||||
typedef struct gcry_mpi *MPI;
|
typedef struct gcry_mpi *MPI;
|
||||||
|
|
||||||
#define MPI_NULL NULL
|
|
||||||
|
|
||||||
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
#define mpi_get_nlimbs(a) ((a)->nlimbs)
|
||||||
#define mpi_is_neg(a) ((a)->sign)
|
#define mpi_is_neg(a) ((a)->sign)
|
||||||
|
|
||||||
|
|
|
@ -279,6 +279,9 @@ config AVERAGE
|
||||||
|
|
||||||
If unsure, say N.
|
If unsure, say N.
|
||||||
|
|
||||||
|
config CLZ_TAB
|
||||||
|
bool
|
||||||
|
|
||||||
config CORDIC
|
config CORDIC
|
||||||
tristate "CORDIC algorithm"
|
tristate "CORDIC algorithm"
|
||||||
help
|
help
|
||||||
|
@ -287,6 +290,7 @@ config CORDIC
|
||||||
|
|
||||||
config MPILIB
|
config MPILIB
|
||||||
tristate
|
tristate
|
||||||
|
select CLZ_TAB
|
||||||
help
|
help
|
||||||
Multiprecision maths library from GnuPG.
|
Multiprecision maths library from GnuPG.
|
||||||
It is used to implement RSA digital signature verification,
|
It is used to implement RSA digital signature verification,
|
||||||
|
|
|
@ -121,6 +121,8 @@ obj-$(CONFIG_DQL) += dynamic_queue_limits.o
|
||||||
obj-$(CONFIG_MPILIB) += mpi/
|
obj-$(CONFIG_MPILIB) += mpi/
|
||||||
obj-$(CONFIG_SIGNATURE) += digsig.o
|
obj-$(CONFIG_SIGNATURE) += digsig.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_CLZ_TAB) += clz_tab.o
|
||||||
|
|
||||||
hostprogs-y := gen_crc32table
|
hostprogs-y := gen_crc32table
|
||||||
clean-files := crc32table.h
|
clean-files := crc32table.h
|
||||||
|
|
||||||
|
|
18
lib/clz_tab.c
Normal file
18
lib/clz_tab.c
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
const unsigned char __clz_tab[] = {
|
||||||
|
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
5, 5, 5, 5, 5, 5, 5, 5,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
6, 6, 6, 6, 6, 6, 6, 6,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
7, 7, 7, 7, 7, 7, 7, 7,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
8, 8, 8, 8, 8, 8, 8, 8,
|
||||||
|
};
|
52
lib/digsig.c
52
lib/digsig.c
|
@ -34,14 +34,9 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||||
unsigned long msglen,
|
unsigned long msglen,
|
||||||
unsigned long modulus_bitlen,
|
unsigned long modulus_bitlen,
|
||||||
unsigned char *out,
|
unsigned char *out,
|
||||||
unsigned long *outlen,
|
unsigned long *outlen)
|
||||||
int *is_valid)
|
|
||||||
{
|
{
|
||||||
unsigned long modulus_len, ps_len, i;
|
unsigned long modulus_len, ps_len, i;
|
||||||
int result;
|
|
||||||
|
|
||||||
/* default to invalid packet */
|
|
||||||
*is_valid = 0;
|
|
||||||
|
|
||||||
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
|
modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
|
||||||
|
|
||||||
|
@ -50,39 +45,30 @@ static int pkcs_1_v1_5_decode_emsa(const unsigned char *msg,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
/* separate encoded message */
|
/* separate encoded message */
|
||||||
if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1)) {
|
if ((msg[0] != 0x00) || (msg[1] != (unsigned char)1))
|
||||||
result = -EINVAL;
|
return -EINVAL;
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 2; i < modulus_len - 1; i++)
|
for (i = 2; i < modulus_len - 1; i++)
|
||||||
if (msg[i] != 0xFF)
|
if (msg[i] != 0xFF)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* separator check */
|
/* separator check */
|
||||||
if (msg[i] != 0) {
|
if (msg[i] != 0)
|
||||||
/* There was no octet with hexadecimal value 0x00
|
/* There was no octet with hexadecimal value 0x00
|
||||||
to separate ps from m. */
|
to separate ps from m. */
|
||||||
result = -EINVAL;
|
return -EINVAL;
|
||||||
goto bail;
|
|
||||||
}
|
|
||||||
|
|
||||||
ps_len = i - 2;
|
ps_len = i - 2;
|
||||||
|
|
||||||
if (*outlen < (msglen - (2 + ps_len + 1))) {
|
if (*outlen < (msglen - (2 + ps_len + 1))) {
|
||||||
*outlen = msglen - (2 + ps_len + 1);
|
*outlen = msglen - (2 + ps_len + 1);
|
||||||
result = -EOVERFLOW;
|
return -EOVERFLOW;
|
||||||
goto bail;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*outlen = (msglen - (2 + ps_len + 1));
|
*outlen = (msglen - (2 + ps_len + 1));
|
||||||
memcpy(out, &msg[2 + ps_len + 1], *outlen);
|
memcpy(out, &msg[2 + ps_len + 1], *outlen);
|
||||||
|
|
||||||
/* valid packet */
|
return 0;
|
||||||
*is_valid = 1;
|
|
||||||
result = 0;
|
|
||||||
bail:
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -96,7 +82,7 @@ static int digsig_verify_rsa(struct key *key,
|
||||||
unsigned long len;
|
unsigned long len;
|
||||||
unsigned long mlen, mblen;
|
unsigned long mlen, mblen;
|
||||||
unsigned nret, l;
|
unsigned nret, l;
|
||||||
int valid, head, i;
|
int head, i;
|
||||||
unsigned char *out1 = NULL, *out2 = NULL;
|
unsigned char *out1 = NULL, *out2 = NULL;
|
||||||
MPI in = NULL, res = NULL, pkey[2];
|
MPI in = NULL, res = NULL, pkey[2];
|
||||||
uint8_t *p, *datap, *endp;
|
uint8_t *p, *datap, *endp;
|
||||||
|
@ -105,6 +91,10 @@ static int digsig_verify_rsa(struct key *key,
|
||||||
|
|
||||||
down_read(&key->sem);
|
down_read(&key->sem);
|
||||||
ukp = key->payload.data;
|
ukp = key->payload.data;
|
||||||
|
|
||||||
|
if (ukp->datalen < sizeof(*pkh))
|
||||||
|
goto err1;
|
||||||
|
|
||||||
pkh = (struct pubkey_hdr *)ukp->data;
|
pkh = (struct pubkey_hdr *)ukp->data;
|
||||||
|
|
||||||
if (pkh->version != 1)
|
if (pkh->version != 1)
|
||||||
|
@ -117,18 +107,23 @@ static int digsig_verify_rsa(struct key *key,
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
datap = pkh->mpi;
|
datap = pkh->mpi;
|
||||||
endp = datap + ukp->datalen;
|
endp = ukp->data + ukp->datalen;
|
||||||
|
|
||||||
|
err = -ENOMEM;
|
||||||
|
|
||||||
for (i = 0; i < pkh->nmpi; i++) {
|
for (i = 0; i < pkh->nmpi; i++) {
|
||||||
unsigned int remaining = endp - datap;
|
unsigned int remaining = endp - datap;
|
||||||
pkey[i] = mpi_read_from_buffer(datap, &remaining);
|
pkey[i] = mpi_read_from_buffer(datap, &remaining);
|
||||||
|
if (!pkey[i])
|
||||||
|
goto err;
|
||||||
datap += remaining;
|
datap += remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
mblen = mpi_get_nbits(pkey[0]);
|
mblen = mpi_get_nbits(pkey[0]);
|
||||||
mlen = (mblen + 7)/8;
|
mlen = (mblen + 7)/8;
|
||||||
|
|
||||||
err = -ENOMEM;
|
if (mlen == 0)
|
||||||
|
goto err;
|
||||||
|
|
||||||
out1 = kzalloc(mlen, GFP_KERNEL);
|
out1 = kzalloc(mlen, GFP_KERNEL);
|
||||||
if (!out1)
|
if (!out1)
|
||||||
|
@ -167,10 +162,9 @@ static int digsig_verify_rsa(struct key *key,
|
||||||
memset(out1, 0, head);
|
memset(out1, 0, head);
|
||||||
memcpy(out1 + head, p, l);
|
memcpy(out1 + head, p, l);
|
||||||
|
|
||||||
err = -EINVAL;
|
err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
|
||||||
pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len, &valid);
|
|
||||||
|
|
||||||
if (valid && len == hlen)
|
if (!err && len == hlen)
|
||||||
err = memcmp(out2, h, hlen);
|
err = memcmp(out2, h, hlen);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -178,8 +172,8 @@ static int digsig_verify_rsa(struct key *key,
|
||||||
mpi_free(res);
|
mpi_free(res);
|
||||||
kfree(out1);
|
kfree(out1);
|
||||||
kfree(out2);
|
kfree(out2);
|
||||||
mpi_free(pkey[0]);
|
while (--i >= 0)
|
||||||
mpi_free(pkey[1]);
|
mpi_free(pkey[i]);
|
||||||
err1:
|
err1:
|
||||||
up_read(&key->sem);
|
up_read(&key->sem);
|
||||||
|
|
||||||
|
|
|
@ -1200,18 +1200,40 @@ do { \
|
||||||
"r" ((USItype)(v)) \
|
"r" ((USItype)(v)) \
|
||||||
: "%g1", "%g2" __AND_CLOBBER_CC)
|
: "%g1", "%g2" __AND_CLOBBER_CC)
|
||||||
#define UMUL_TIME 39 /* 39 instructions */
|
#define UMUL_TIME 39 /* 39 instructions */
|
||||||
#endif
|
/* It's quite necessary to add this much assembler for the sparc.
|
||||||
#ifndef udiv_qrnnd
|
The default udiv_qrnnd (in C) is more than 10 times slower! */
|
||||||
#ifndef LONGLONG_STANDALONE
|
|
||||||
#define udiv_qrnnd(q, r, n1, n0, d) \
|
#define udiv_qrnnd(q, r, n1, n0, d) \
|
||||||
do { USItype __r; \
|
__asm__ ("! Inlined udiv_qrnnd\n\t" \
|
||||||
(q) = __udiv_qrnnd(&__r, (n1), (n0), (d)); \
|
"mov 32,%%g1\n\t" \
|
||||||
(r) = __r; \
|
"subcc %1,%2,%%g0\n\t" \
|
||||||
} while (0)
|
"1: bcs 5f\n\t" \
|
||||||
extern USItype __udiv_qrnnd();
|
"addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
|
||||||
#define UDIV_TIME 140
|
"sub %1,%2,%1 ! this kills msb of n\n\t" \
|
||||||
#endif /* LONGLONG_STANDALONE */
|
"addx %1,%1,%1 ! so this can't give carry\n\t" \
|
||||||
#endif /* udiv_qrnnd */
|
"subcc %%g1,1,%%g1\n\t" \
|
||||||
|
"2: bne 1b\n\t" \
|
||||||
|
"subcc %1,%2,%%g0\n\t" \
|
||||||
|
"bcs 3f\n\t" \
|
||||||
|
"addxcc %0,%0,%0 ! shift n1n0 and a q-bit in lsb\n\t" \
|
||||||
|
"b 3f\n\t" \
|
||||||
|
"sub %1,%2,%1 ! this kills msb of n\n\t" \
|
||||||
|
"4: sub %1,%2,%1\n\t" \
|
||||||
|
"5: addxcc %1,%1,%1\n\t" \
|
||||||
|
"bcc 2b\n\t" \
|
||||||
|
"subcc %%g1,1,%%g1\n\t" \
|
||||||
|
"! Got carry from n. Subtract next step to cancel this carry.\n\t" \
|
||||||
|
"bne 4b\n\t" \
|
||||||
|
"addcc %0,%0,%0 ! shift n1n0 and a 0-bit in lsb\n\t" \
|
||||||
|
"sub %1,%2,%1\n\t" \
|
||||||
|
"3: xnor %0,0,%0\n\t" \
|
||||||
|
"! End of inline udiv_qrnnd\n" \
|
||||||
|
: "=&r" ((USItype)(q)), \
|
||||||
|
"=&r" ((USItype)(r)) \
|
||||||
|
: "r" ((USItype)(d)), \
|
||||||
|
"1" ((USItype)(n1)), \
|
||||||
|
"0" ((USItype)(n0)) : "%g1", "cc")
|
||||||
|
#define UDIV_TIME (3+7*32) /* 7 instructions/iteration. 32 iterations. */
|
||||||
|
#endif
|
||||||
#endif /* __sparc__ */
|
#endif /* __sparc__ */
|
||||||
|
|
||||||
/***************************************
|
/***************************************
|
||||||
|
|
|
@ -21,25 +21,6 @@
|
||||||
#include "mpi-internal.h"
|
#include "mpi-internal.h"
|
||||||
#include "longlong.h"
|
#include "longlong.h"
|
||||||
|
|
||||||
const unsigned char __clz_tab[] = {
|
|
||||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5,
|
|
||||||
5, 5, 5, 5, 5, 5, 5, 5,
|
|
||||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
|
||||||
6, 6, 6, 6, 6, 6, 6, 6,
|
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
||||||
7, 7, 7, 7, 7, 7, 7, 7,
|
|
||||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
|
||||||
7, 7, 7, 7, 7, 7, 7, 7,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
8, 8, 8, 8, 8, 8, 8, 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
#define A_LIMB_1 ((mpi_limb_t) 1)
|
#define A_LIMB_1 ((mpi_limb_t) 1)
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
|
|
|
@ -149,6 +149,9 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
|
||||||
mpi_ptr_t marker[5];
|
mpi_ptr_t marker[5];
|
||||||
int markidx = 0;
|
int markidx = 0;
|
||||||
|
|
||||||
|
if (!dsize)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
memset(marker, 0, sizeof(marker));
|
memset(marker, 0, sizeof(marker));
|
||||||
|
|
||||||
/* Ensure space is enough for quotient and remainder.
|
/* Ensure space is enough for quotient and remainder.
|
||||||
|
@ -207,6 +210,8 @@ int mpi_tdiv_qr(MPI quot, MPI rem, MPI num, MPI den)
|
||||||
* numerator would be gradually overwritten by the quotient limbs. */
|
* numerator would be gradually overwritten by the quotient limbs. */
|
||||||
if (qp == np) { /* Copy NP object to temporary space. */
|
if (qp == np) { /* Copy NP object to temporary space. */
|
||||||
np = marker[markidx++] = mpi_alloc_limb_space(nsize);
|
np = marker[markidx++] = mpi_alloc_limb_space(nsize);
|
||||||
|
if (!np)
|
||||||
|
goto nomem;
|
||||||
MPN_COPY(np, qp, nsize);
|
MPN_COPY(np, qp, nsize);
|
||||||
}
|
}
|
||||||
} else /* Put quotient at top of remainder. */
|
} else /* Put quotient at top of remainder. */
|
||||||
|
|
|
@ -59,7 +59,7 @@ int mpi_powm(MPI res, MPI base, MPI exp, MPI mod)
|
||||||
ep = exp->d;
|
ep = exp->d;
|
||||||
|
|
||||||
if (!msize)
|
if (!msize)
|
||||||
msize = 1 / msize; /* provoke a signal */
|
return -EINVAL;
|
||||||
|
|
||||||
if (!esize) {
|
if (!esize) {
|
||||||
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
|
/* Exponent is zero, result is 1 mod MOD, i.e., 1 or 0
|
||||||
|
|
|
@ -20,78 +20,15 @@
|
||||||
|
|
||||||
#include "mpi-internal.h"
|
#include "mpi-internal.h"
|
||||||
|
|
||||||
#define DIM(v) (sizeof(v)/sizeof((v)[0]))
|
|
||||||
#define MAX_EXTERN_MPI_BITS 16384
|
#define MAX_EXTERN_MPI_BITS 16384
|
||||||
|
|
||||||
static uint8_t asn[15] = /* Object ID is 1.3.14.3.2.26 */
|
|
||||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
|
||||||
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14
|
|
||||||
};
|
|
||||||
|
|
||||||
MPI do_encode_md(const void *sha_buffer, unsigned nbits)
|
|
||||||
{
|
|
||||||
int nframe = (nbits + 7) / 8;
|
|
||||||
uint8_t *frame, *fr_pt;
|
|
||||||
int i = 0, n;
|
|
||||||
size_t asnlen = DIM(asn);
|
|
||||||
MPI a = MPI_NULL;
|
|
||||||
|
|
||||||
if (SHA1_DIGEST_LENGTH + asnlen + 4 > nframe)
|
|
||||||
pr_info("MPI: can't encode a %d bit MD into a %d bits frame\n",
|
|
||||||
(int)(SHA1_DIGEST_LENGTH * 8), (int)nbits);
|
|
||||||
|
|
||||||
/* We encode the MD in this way:
|
|
||||||
*
|
|
||||||
* 0 A PAD(n bytes) 0 ASN(asnlen bytes) MD(len bytes)
|
|
||||||
*
|
|
||||||
* PAD consists of FF bytes.
|
|
||||||
*/
|
|
||||||
frame = kmalloc(nframe, GFP_KERNEL);
|
|
||||||
if (!frame)
|
|
||||||
return MPI_NULL;
|
|
||||||
n = 0;
|
|
||||||
frame[n++] = 0;
|
|
||||||
frame[n++] = 1; /* block type */
|
|
||||||
i = nframe - SHA1_DIGEST_LENGTH - asnlen - 3;
|
|
||||||
|
|
||||||
if (i <= 1) {
|
|
||||||
pr_info("MPI: message digest encoding failed\n");
|
|
||||||
kfree(frame);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(frame + n, 0xff, i);
|
|
||||||
n += i;
|
|
||||||
frame[n++] = 0;
|
|
||||||
memcpy(frame + n, &asn, asnlen);
|
|
||||||
n += asnlen;
|
|
||||||
memcpy(frame + n, sha_buffer, SHA1_DIGEST_LENGTH);
|
|
||||||
n += SHA1_DIGEST_LENGTH;
|
|
||||||
|
|
||||||
i = nframe;
|
|
||||||
fr_pt = frame;
|
|
||||||
|
|
||||||
if (n != nframe) {
|
|
||||||
printk
|
|
||||||
("MPI: message digest encoding failed, frame length is wrong\n");
|
|
||||||
kfree(frame);
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = mpi_alloc((nframe + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB);
|
|
||||||
mpi_set_buffer(a, frame, nframe, 0);
|
|
||||||
kfree(frame);
|
|
||||||
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
|
MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
|
||||||
{
|
{
|
||||||
const uint8_t *buffer = xbuffer;
|
const uint8_t *buffer = xbuffer;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned nbits, nbytes, nlimbs, nread = 0;
|
unsigned nbits, nbytes, nlimbs, nread = 0;
|
||||||
mpi_limb_t a;
|
mpi_limb_t a;
|
||||||
MPI val = MPI_NULL;
|
MPI val = NULL;
|
||||||
|
|
||||||
if (*ret_nread < 2)
|
if (*ret_nread < 2)
|
||||||
goto leave;
|
goto leave;
|
||||||
|
@ -108,7 +45,7 @@ MPI mpi_read_from_buffer(const void *xbuffer, unsigned *ret_nread)
|
||||||
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
nlimbs = (nbytes + BYTES_PER_MPI_LIMB - 1) / BYTES_PER_MPI_LIMB;
|
||||||
val = mpi_alloc(nlimbs);
|
val = mpi_alloc(nlimbs);
|
||||||
if (!val)
|
if (!val)
|
||||||
return MPI_NULL;
|
return NULL;
|
||||||
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
i = BYTES_PER_MPI_LIMB - nbytes % BYTES_PER_MPI_LIMB;
|
||||||
i %= BYTES_PER_MPI_LIMB;
|
i %= BYTES_PER_MPI_LIMB;
|
||||||
val->nbits = nbits;
|
val->nbits = nbits;
|
||||||
|
@ -211,30 +148,6 @@ int mpi_fromstr(MPI val, const char *str)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mpi_fromstr);
|
EXPORT_SYMBOL_GPL(mpi_fromstr);
|
||||||
|
|
||||||
/****************
|
|
||||||
* Special function to get the low 8 bytes from an mpi.
|
|
||||||
* This can be used as a keyid; KEYID is an 2 element array.
|
|
||||||
* Return the low 4 bytes.
|
|
||||||
*/
|
|
||||||
u32 mpi_get_keyid(const MPI a, u32 *keyid)
|
|
||||||
{
|
|
||||||
#if BYTES_PER_MPI_LIMB == 4
|
|
||||||
if (keyid) {
|
|
||||||
keyid[0] = a->nlimbs >= 2 ? a->d[1] : 0;
|
|
||||||
keyid[1] = a->nlimbs >= 1 ? a->d[0] : 0;
|
|
||||||
}
|
|
||||||
return a->nlimbs >= 1 ? a->d[0] : 0;
|
|
||||||
#elif BYTES_PER_MPI_LIMB == 8
|
|
||||||
if (keyid) {
|
|
||||||
keyid[0] = a->nlimbs ? (u32) (a->d[0] >> 32) : 0;
|
|
||||||
keyid[1] = a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
|
|
||||||
}
|
|
||||||
return a->nlimbs ? (u32) (a->d[0] & 0xffffffff) : 0;
|
|
||||||
#else
|
|
||||||
#error Make this function work with other LIMB sizes
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************
|
/****************
|
||||||
* Return an allocated buffer with the MPI (msb first).
|
* Return an allocated buffer with the MPI (msb first).
|
||||||
* NBYTES receives the length of this buffer. Caller must free the
|
* NBYTES receives the length of this buffer. Caller must free the
|
||||||
|
|
|
@ -217,6 +217,10 @@ mpihelp_divrem(mpi_ptr_t qp, mpi_size_t qextra_limbs,
|
||||||
case 0:
|
case 0:
|
||||||
/* We are asked to divide by zero, so go ahead and do it! (To make
|
/* We are asked to divide by zero, so go ahead and do it! (To make
|
||||||
the compiler not remove this statement, return the value.) */
|
the compiler not remove this statement, return the value.) */
|
||||||
|
/*
|
||||||
|
* existing clients of this function have been modified
|
||||||
|
* not to call it with dsize == 0, so this should not happen
|
||||||
|
*/
|
||||||
return 1 / dsize;
|
return 1 / dsize;
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
|
|
@ -58,6 +58,9 @@ mpi_ptr_t mpi_alloc_limb_space(unsigned nlimbs)
|
||||||
{
|
{
|
||||||
size_t len = nlimbs * sizeof(mpi_limb_t);
|
size_t len = nlimbs * sizeof(mpi_limb_t);
|
||||||
|
|
||||||
|
if (!len)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return kmalloc(len, GFP_KERNEL);
|
return kmalloc(len, GFP_KERNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +138,7 @@ int mpi_copy(MPI *copied, const MPI a)
|
||||||
size_t i;
|
size_t i;
|
||||||
MPI b;
|
MPI b;
|
||||||
|
|
||||||
*copied = MPI_NULL;
|
*copied = NULL;
|
||||||
|
|
||||||
if (a) {
|
if (a) {
|
||||||
b = mpi_alloc(a->nlimbs);
|
b = mpi_alloc(a->nlimbs);
|
||||||
|
|
Loading…
Reference in a new issue