comparison libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c @ 285:1b9e69c058d2

propagate from branch 'au.asn.ucc.matt.ltc.dropbear' (head 20dccfc09627970a312d77fb41dc2970b62689c3) to branch 'au.asn.ucc.matt.dropbear' (head fdf4a7a3b97ae5046139915de7e40399cceb2c01)
author Matt Johnston <matt@ucc.asn.au>
date Wed, 08 Mar 2006 13:23:58 +0000
parents
children 0cbe8f6dbf9e
comparison
equal deleted inserted replaced
281:997e6f7dc01e 285:1b9e69c058d2
1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, [email protected], http://libtomcrypt.org
10 */
11 #include "tomcrypt.h"
12
13 /**
14 @file der_encode_integer.c
15 ASN.1 DER, encode an integer, Tom St Denis
16 */
17
18
19 #ifdef LTC_DER
20
21 /* Exports a positive bignum as DER format (upto 2^32 bytes in size) */
22 /**
23 Store a mp_int integer
24 @param num The first mp_int to encode
25 @param out [out] The destination for the DER encoded integers
26 @param outlen [in/out] The max size and resulting size of the DER encoded integers
27 @return CRYPT_OK if successful
28 */
29 int der_encode_integer(mp_int *num, unsigned char *out, unsigned long *outlen)
30 {
31 unsigned long tmplen, y;
32 int err, leading_zero;
33
34 LTC_ARGCHK(num != NULL);
35 LTC_ARGCHK(out != NULL);
36 LTC_ARGCHK(outlen != NULL);
37
38 /* find out how big this will be */
39 if ((err = der_length_integer(num, &tmplen)) != CRYPT_OK) {
40 return err;
41 }
42
43 if (*outlen < tmplen) {
44 return CRYPT_BUFFER_OVERFLOW;
45 }
46
47 if (mp_cmp_d(num, 0) != MP_LT) {
48 /* we only need a leading zero if the msb of the first byte is one */
49 if ((mp_count_bits(num) & 7) == 0 || mp_iszero(num) == MP_YES) {
50 leading_zero = 1;
51 } else {
52 leading_zero = 0;
53 }
54
55 /* get length of num in bytes (plus 1 since we force the msbyte to zero) */
56 y = mp_unsigned_bin_size(num) + leading_zero;
57 } else {
58 leading_zero = 0;
59 y = mp_count_bits(num);
60 y = y + (8 - (y & 7));
61 y = y >> 3;
62
63 }
64
65 /* now store initial data */
66 *out++ = 0x02;
67 if (y < 128) {
68 /* short form */
69 *out++ = (unsigned char)y;
70 } else if (y < 256) {
71 *out++ = 0x81;
72 *out++ = y;
73 } else if (y < 65536UL) {
74 *out++ = 0x82;
75 *out++ = (y>>8)&255;
76 *out++ = y;
77 } else if (y < 16777216UL) {
78 *out++ = 0x83;
79 *out++ = (y>>16)&255;
80 *out++ = (y>>8)&255;
81 *out++ = y;
82 } else {
83 return CRYPT_INVALID_ARG;
84 }
85
86 /* now store msbyte of zero if num is non-zero */
87 if (leading_zero) {
88 *out++ = 0x00;
89 }
90
91 /* if it's not zero store it as big endian */
92 if (mp_cmp_d(num, 0) == MP_GT) {
93 /* now store the mpint */
94 if ((err = mp_to_unsigned_bin(num, out)) != MP_OKAY) {
95 return mpi_to_ltc_error(err);
96 }
97 } else if (mp_iszero(num) != MP_YES) {
98 mp_int tmp;
99 /* negative */
100 if (mp_init(&tmp) != MP_OKAY) {
101 return CRYPT_MEM;
102 }
103
104 /* 2^roundup and subtract */
105 y = mp_count_bits(num);
106 y = y + (8 - (y & 7));
107 if (mp_2expt(&tmp, y) != MP_OKAY || mp_add(&tmp, num, &tmp) != MP_OKAY) {
108 mp_clear(&tmp);
109 return CRYPT_MEM;
110 }
111
112 if ((err = mp_to_unsigned_bin(&tmp, out)) != MP_OKAY) {
113 mp_clear(&tmp);
114 return mpi_to_ltc_error(err);
115 }
116 mp_clear(&tmp);
117 }
118
119 /* we good */
120 *outlen = tmplen;
121 return CRYPT_OK;
122 }
123
124 #endif
125
126 /* $Source: /cvs/libtom/libtomcrypt/src/pk/asn1/der/integer/der_encode_integer.c,v $ */
127 /* $Revision: 1.1 $ */
128 /* $Date: 2005/05/16 15:08:11 $ */