1/*
2 * Copyright (c) 2011-12 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23/* x_long.c */
24/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
25 * project 2000.
26 */
27/* ====================================================================
28 * Copyright (c) 2000 The OpenSSL Project.  All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions
32 * are met:
33 *
34 * 1. Redistributions of source code must retain the above copyright
35 *    notice, this list of conditions and the following disclaimer.
36 *
37 * 2. Redistributions in binary form must reproduce the above copyright
38 *    notice, this list of conditions and the following disclaimer in
39 *    the documentation and/or other materials provided with the
40 *    distribution.
41 *
42 * 3. All advertising materials mentioning features or use of this
43 *    software must display the following acknowledgment:
44 *    "This product includes software developed by the OpenSSL Project
45 *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
46 *
47 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
48 *    endorse or promote products derived from this software without
49 *    prior written permission. For written permission, please contact
50 *    licensing@OpenSSL.org.
51 *
52 * 5. Products derived from this software may not be called "OpenSSL"
53 *    nor may "OpenSSL" appear in their names without prior written
54 *    permission of the OpenSSL Project.
55 *
56 * 6. Redistributions of any form whatsoever must retain the following
57 *    acknowledgment:
58 *    "This product includes software developed by the OpenSSL Project
59 *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
60 *
61 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
62 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
63 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
64 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
65 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
66 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
67 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
68 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
69 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
70 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
71 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
72 * OF THE POSSIBILITY OF SUCH DAMAGE.
73 * ====================================================================
74 *
75 * This product includes cryptographic software written by Eric Young
76 * (eay@cryptsoft.com).  This product includes software written by Tim
77 * Hudson (tjh@cryptsoft.com).
78 *
79 */
80
81#include <sys/types.h>
82
83#include <stdio.h>
84#include <stdlib.h>
85#include <string.h>
86
87#if 0
88#include "cryptlib.h"
89#include <openssl/asn1t.h>
90#include <openssl/bn.h>
91
92#else
93
94#include "cs-asn1t.h"
95#include "cs-bn.h"
96#endif
97
98/* Custom primitive type for long handling. This converts between an ASN1_INTEGER
99 * and a long directly.
100 */
101
102
103static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it);
104static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it);
105
106static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it);
107static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len, int utype, char *free_cont, const ASN1_ITEM *it);
108
109static ASN1_PRIMITIVE_FUNCS long_pf = {
110	NULL, 0,
111	long_new,
112	long_free,
113	long_free,	/* Clear should set to initial value */
114	long_c2i,
115	long_i2c
116};
117
118ASN1_ITEM_start(LONG)
119	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, ASN1_LONG_UNDEF, "LONG"
120ASN1_ITEM_end(LONG)
121
122ASN1_ITEM_start(ZLONG)
123	ASN1_ITYPE_PRIMITIVE, V_ASN1_INTEGER, NULL, 0, &long_pf, 0, "ZLONG"
124ASN1_ITEM_end(ZLONG)
125
126static int long_new(ASN1_VALUE **pval, const ASN1_ITEM *it)
127{
128	*(long *)pval = it->size;
129	return 1;
130}
131
132static void long_free(ASN1_VALUE **pval, const ASN1_ITEM *it)
133{
134	*(long *)pval = it->size;
135}
136
137static int long_i2c(ASN1_VALUE **pval, unsigned char *cont, int *putype, const ASN1_ITEM *it)
138{
139	long ltmp;
140	unsigned long utmp;
141	int clen, pad, i;
142	/* this exists to bypass broken gcc optimization */
143	char *cp = (char *)pval;
144
145	/* use memcpy, because we may not be long aligned */
146	memcpy(&ltmp, cp, sizeof(long));
147
148	if(ltmp == it->size) return -1;
149	/* Convert the long to positive: we subtract one if negative so
150	 * we can cleanly handle the padding if only the MSB of the leading
151	 * octet is set.
152	 */
153	if(ltmp < 0) utmp = -ltmp - 1;
154	else utmp = ltmp;
155	clen = BN_num_bits_word(utmp);
156	/* If MSB of leading octet set we need to pad */
157	if(!(clen & 0x7)) pad = 1;
158	else pad = 0;
159
160	/* Convert number of bits to number of octets */
161	clen = (clen + 7) >> 3;
162
163	if(cont) {
164		if(pad) *cont++ = (ltmp < 0) ? 0xff : 0;
165		for(i = clen - 1; i >= 0; i--) {
166			cont[i] = (unsigned char)(utmp & 0xff);
167			if(ltmp < 0) cont[i] ^= 0xff;
168			utmp >>= 8;
169		}
170	}
171	return clen + pad;
172}
173
174static int long_c2i(ASN1_VALUE **pval, const unsigned char *cont, int len,
175		    int utype, char *free_cont, const ASN1_ITEM *it)
176{
177	int neg, i;
178	long ltmp;
179	unsigned long utmp = 0;
180	char *cp = (char *)pval;
181	if(len > (int)sizeof(long)) {
182		/* ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); */
183		return 0;
184	}
185	/* Is it negative? */
186	if(len && (cont[0] & 0x80)) neg = 1;
187	else neg = 0;
188	utmp = 0;
189	for(i = 0; i < len; i++) {
190		utmp <<= 8;
191		if(neg) utmp |= cont[i] ^ 0xff;
192		else utmp |= cont[i];
193	}
194	ltmp = (long)utmp;
195	if(neg) {
196		ltmp++;
197		ltmp = -ltmp;
198	}
199	if(ltmp == it->size) {
200		/* ASN1err(ASN1_F_LONG_C2I, ASN1_R_INTEGER_TOO_LARGE_FOR_LONG); */
201		return 0;
202	}
203	memcpy(cp, &ltmp, sizeof(long));
204	return 1;
205}
206