Crypt-Bear

 view release on metacpan or  search on metacpan

src/x509/asn1.t0  view on Meta::CPAN

		read8 x dup 0xFFFFFF >= if ERR_X509_OVERFLOW fail then
		8 << + >x
	repeat
	drop x ;

\ Compare the OID in the pad with an OID in the constant data block.
\ Returned value is -1 on equality, 0 otherwise.
cc: eqOID ( addrConst -- bool ) {
	const unsigned char *a2 = &t0_datablock[T0_POP()];
	const unsigned char *a1 = &CTX->pad[0];
	size_t len = a1[0];
	int x;
	if (len == a2[0]) {
		x = -(memcmp(a1 + 1, a2 + 1, len) == 0);
	} else {
		x = 0;
	}
	T0_PUSH((uint32_t)x);
}

\ Compare two blobs in the context. Returned value is -1 on equality, 0
\ otherwise.
cc: eqblob ( addr1 addr2 len -- bool ) {
	size_t len = T0_POP();
	const unsigned char *a2 = (const unsigned char *)CTX + T0_POP();
	const unsigned char *a1 = (const unsigned char *)CTX + T0_POP();
	T0_PUSHi(-(memcmp(a1, a2, len) == 0));
}

\ Check that a value is in a given range (inclusive).
: between? ( x min max -- bool )
	{ min max } dup min >= swap max <= and ;

\ Convert the provided byte value into a number in the 0..9 range,
\ assuming that it is an ASCII digit. A non-digit triggers an error
\ (a "bad time" error since this is used in date/time decoding).
: digit-dec ( char -- value )
	`0 - dup 0 9 between? ifnot ERR_X509_BAD_TIME fail then ;

\ Read two ASCII digits and return the value in the 0..99 range. An
\ error is reported if the characters are not ASCII digits.
: read-dec2 ( lim -- lim x )
	read8 digit-dec 10 * { x } read8 digit-dec x + ;

\ Read two ASCII digits and check that the value is in the provided
\ range (inclusive).
: read-dec2-range ( lim min max -- lim x )
	{ min max }
	read-dec2 dup min max between? ifnot ERR_X509_BAD_TIME fail then ;

\ Maximum days in a month and accumulated day count. Each
\ 16-bit value contains the month day count in its lower 5 bits. The first
\ 12 values are for a normal year, the other 12 for a leap year.
data: month-to-days
hexb| 001F 03FC 077F 0B5E 0F1F 12FE 16BF 1A9F 1E7E 223F 261E 29DF |
hexb| 001F 03FD 079F 0B7E 0F3F 131E 16DF 1ABF 1E9E 225F 263E 29FF |

\ Read a date (UTCTime or GeneralizedTime). The date value is converted
\ to a day count and a second count. The day count starts at 0 for
\ January 1st, 0 AD (that's they year before 1 AD, also known as 1 BC)
\ in a proleptic Gregorian calendar (i.e. Gregorian rules are assumed to
\ extend indefinitely in the past). The second count is between 0 and
\ 86400 (inclusive, in case of a leap second).
: read-date ( lim -- lim days seconds )
	\ Read tag; must be UTCTime or GeneralizedTime. Year count is
	\ 4 digits with GeneralizedTime, 2 digits with UTCTime.
	read-tag
	dup 0x17 0x18 between? ifnot ERR_X509_BAD_TIME fail then
	0x18 = { y4d }
	check-primitive
	read-length-open-elt

	\ We compute the days and seconds counts during decoding, in
	\ order to minimize the number of needed temporary variables.
	{ ; days seconds x }

	\ Year is 4-digit with GeneralizedTime. With UTCTime, the year
	\ is in the 1950..2049 range, and only the last two digits are
	\ present in the encoding.
	read-dec2
	y4d if
		100 * >x read-dec2 x +
	else
		dup 50 < if 100 + then 1900 +
	then
	>x
	x 365 * x 3 + 4 / + x 99 + 100 / - x 399 + 400 / + >days

	\ Month is 1..12. Number of days in a months depend on the
	\ month and on the year (year count is in x at that point).
	1 12 read-dec2-range
	1- 1 <<
	x 4 % 0= x 100 % 0<> x 400 % 0= or and if 24 + then
	month-to-days + data-get16
	dup 5 >> days + >days
	0x1F and

	\ Day. At this point, the TOS contains the maximum day count for
	\ the current month.
	1 swap read-dec2-range
	days + 1- >days

	\ Hour, minute and seconds. Count of seconds is allowed to go to
	\ 60 in case of leap seconds (in practice, leap seconds really
	\ occur only at the very end of the day, so this computation is
	\ exact for a real leap second, and a spurious leap second only
	\ implies a one-second shift that we can ignore).
	0 23 read-dec2-range 3600 * >seconds
	0 59 read-dec2-range 60 * seconds + >seconds
	0 60 read-dec2-range seconds + >seconds

	\ At this point, we may have fractional seconds. This should
	\ happen only with GeneralizedTime, but we accept it for UTCTime
	\ too (and, anyway, we ignore these fractional seconds).
	read8 dup `. = if
		drop
		begin read8 dup `0 `9 between? while drop repeat
	then

	\ The time zone should be 'Z', not followed by anything. Other
	\ time zone indications are not DER and thus not supposed to



( run in 2.033 seconds using v1.01-cache-2.11-cpan-df04353d9ac )