PageRenderTime 52ms CodeModel.GetById 11ms app.highlight 36ms RepoModel.GetById 1ms app.codeStats 0ms

/security/nss/lib/util/dersubr.c

http://github.com/zpao/v8monkey
C | 266 lines | 187 code | 19 blank | 60 comment | 51 complexity | f1ebf2325621ef43f7906414b0baac1c MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the Netscape security libraries.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Netscape Communications Corporation.
 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 19 * the Initial Developer. All Rights Reserved.
 20 *
 21 * Contributor(s):
 22 *
 23 * Alternatively, the contents of this file may be used under the terms of
 24 * either the GNU General Public License Version 2 or later (the "GPL"), or
 25 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 26 * in which case the provisions of the GPL or the LGPL are applicable instead
 27 * of those above. If you wish to allow use of your version of this file only
 28 * under the terms of either the GPL or the LGPL, and not to allow others to
 29 * use your version of this file under the terms of the MPL, indicate your
 30 * decision by deleting the provisions above and replace them with the notice
 31 * and other provisions required by the GPL or the LGPL. If you do not delete
 32 * the provisions above, a recipient may use your version of this file under
 33 * the terms of any one of the MPL, the GPL or the LGPL.
 34 *
 35 * ***** END LICENSE BLOCK ***** */
 36
 37#include "secder.h"
 38#include <limits.h>
 39#include "secerr.h"
 40
 41int
 42DER_LengthLength(PRUint32 len)
 43{
 44    if (len > 127) {
 45	if (len > 255) {
 46	    if (len > 65535L) {
 47		if (len > 16777215L) {
 48		    return 5;
 49		} else {
 50		    return 4;
 51		}
 52	    } else {
 53		return 3;
 54	    }
 55	} else {
 56	    return 2;
 57	}
 58    } else {
 59	return 1;
 60    }
 61}
 62
 63unsigned char *
 64DER_StoreHeader(unsigned char *buf, unsigned int code, PRUint32 len)
 65{
 66    unsigned char b[4];
 67
 68    b[0] = (unsigned char)(len >> 24);
 69    b[1] = (unsigned char)(len >> 16);
 70    b[2] = (unsigned char)(len >> 8);
 71    b[3] = (unsigned char)len;
 72    if ((code & DER_TAGNUM_MASK) == DER_SET
 73	|| (code & DER_TAGNUM_MASK) == DER_SEQUENCE)
 74	code |= DER_CONSTRUCTED;
 75    *buf++ = code;
 76    if (len > 127) {
 77	if (len > 255) {
 78	    if (len > 65535) {
 79		if (len > 16777215) {
 80		    *buf++ = 0x84;
 81		    *buf++ = b[0];
 82		    *buf++ = b[1];
 83		    *buf++ = b[2];
 84		    *buf++ = b[3];
 85		} else {
 86		    *buf++ = 0x83;
 87		    *buf++ = b[1];
 88		    *buf++ = b[2];
 89		    *buf++ = b[3];
 90		}
 91	    } else {
 92		*buf++ = 0x82;
 93		*buf++ = b[2];
 94		*buf++ = b[3];
 95	    }
 96	} else {
 97	    *buf++ = 0x81;
 98	    *buf++ = b[3];
 99	}
100    } else {
101	*buf++ = b[3];
102    }
103    return buf;
104}
105
106/*
107 * XXX This should be rewritten, generalized, to take a long instead
108 * of a PRInt32.
109 */
110SECStatus
111DER_SetInteger(PRArenaPool *arena, SECItem *it, PRInt32 i)
112{
113    unsigned char bb[4];
114    unsigned len;
115
116    bb[0] = (unsigned char) (i >> 24);
117    bb[1] = (unsigned char) (i >> 16);
118    bb[2] = (unsigned char) (i >> 8);
119    bb[3] = (unsigned char) (i);
120
121    /*
122    ** Small integers are encoded in a single byte. Larger integers
123    ** require progressively more space.
124    */
125    if (i < -128) {
126	if (i < -32768L) {
127	    if (i < -8388608L) {
128		len = 4;
129	    } else {
130		len = 3;
131	    }
132	} else {
133	    len = 2;
134	}
135    } else if (i > 127) {
136	if (i > 32767L) {
137	    if (i > 8388607L) {
138		len = 4;
139	    } else {
140		len = 3;
141	    }
142	} else {
143	    len = 2;
144	}
145    } else {
146	len = 1;
147    }
148    it->data = (unsigned char*) PORT_ArenaAlloc(arena, len);
149    if (!it->data) {
150	return SECFailure;
151    }
152    it->len = len;
153    PORT_Memcpy(it->data, bb + (4 - len), len);
154    return SECSuccess;
155}
156
157/*
158 * XXX This should be rewritten, generalized, to take an unsigned long instead
159 * of a PRUint32.
160 */
161SECStatus
162DER_SetUInteger(PRArenaPool *arena, SECItem *it, PRUint32 ui)
163{
164    unsigned char bb[5];
165    int len;
166
167    bb[0] = 0;
168    bb[1] = (unsigned char) (ui >> 24);
169    bb[2] = (unsigned char) (ui >> 16);
170    bb[3] = (unsigned char) (ui >> 8);
171    bb[4] = (unsigned char) (ui);
172
173    /*
174    ** Small integers are encoded in a single byte. Larger integers
175    ** require progressively more space.
176    */
177    if (ui > 0x7f) {
178	if (ui > 0x7fff) {
179	    if (ui > 0x7fffffL) {
180		if (ui >= 0x80000000L) {
181		    len = 5;
182		} else {
183		    len = 4;
184		}
185	    } else {
186		len = 3;
187	    }
188	} else {
189	    len = 2;
190	}
191    } else {
192	len = 1;
193    }
194
195    it->data = (unsigned char *)PORT_ArenaAlloc(arena, len);
196    if (it->data == NULL) {
197	return SECFailure;
198    }
199
200    it->len = len;
201    PORT_Memcpy(it->data, bb + (sizeof(bb) - len), len);
202
203    return SECSuccess;
204}
205
206/*
207** Convert a der encoded *signed* integer into a machine integral value.
208** If an underflow/overflow occurs, sets error code and returns min/max.
209*/
210long
211DER_GetInteger(SECItem *it)
212{
213    long ival = 0;
214    unsigned len = it->len;
215    unsigned char *cp = it->data;
216    unsigned long overflow = 0x1ffUL << (((sizeof(ival) - 1) * 8) - 1);
217    unsigned long ofloinit;
218
219    if (*cp & 0x80)
220    	ival = -1L;
221    ofloinit = ival & overflow;
222
223    while (len) {
224	if ((ival & overflow) != ofloinit) {
225	    PORT_SetError(SEC_ERROR_BAD_DER);
226	    if (ival < 0) {
227		return LONG_MIN;
228	    }
229	    return LONG_MAX;
230	}
231	ival = ival << 8;
232	ival |= *cp++;
233	--len;
234    }
235    return ival;
236}
237
238/*
239** Convert a der encoded *unsigned* integer into a machine integral value.
240** If an underflow/overflow occurs, sets error code and returns min/max.
241*/
242unsigned long
243DER_GetUInteger(SECItem *it)
244{
245    unsigned long ival = 0;
246    unsigned len = it->len;
247    unsigned char *cp = it->data;
248    unsigned long overflow = 0xffUL << ((sizeof(ival) - 1) * 8);
249
250    /* Cannot put a negative value into an unsigned container. */
251    if (*cp & 0x80) {
252	PORT_SetError(SEC_ERROR_BAD_DER);
253	return 0;
254    }
255
256    while (len) {
257	if (ival & overflow) {
258	    PORT_SetError(SEC_ERROR_BAD_DER);
259	    return ULONG_MAX;
260	}
261	ival = ival << 8;
262	ival |= *cp++;
263	--len;
264    }
265    return ival;
266}