Crypt-Bear

 view release on metacpan or  search on metacpan

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

	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
	\ appear in certificates.
	`Z <> if ERR_X509_BAD_TIME fail then
	close-elt
	days seconds ;

\ Read an INTEGER (tag, length and value). The INTEGER is supposed to be
\ positive; its unsigned big-endian encoding is stored in the provided
\ in-context buffer. Returned value is the decoded length. If the integer
\ did not fit, or the value is negative, then an error is reported.
: read-integer ( lim addr len -- lim dlen )
	rot read-tag 0x02 check-tag-primitive -rot
	read-integer-next ;

\ Identical to read-integer, but the tag has already been read and checked.
: read-integer-next ( lim addr len -- lim dlen )
	dup { addr len origlen }
	read-length-open-elt
	\ Read first byte; sign bit must be 0.
	read8 dup 0x80 >= if ERR_X509_OVERFLOW fail then
	\ Skip leading bytes of value 0. If there are only bytes of
	\ value 0, then return.
	begin dup 0 = while
		drop dup ifnot drop 0 ret then
		read8
	repeat
	\ At that point, we have the first non-zero byte on the stack.
	begin
		len dup ifnot ERR_X509_LIMIT_EXCEEDED fail then 1- >len
		addr set8 addr 1+ >addr
		dup while read8
	repeat
	drop origlen len - ;

\ Read a BOOLEAN value. This should be called immediately after reading
\ the tag.
: read-boolean ( lim constructed value -- lim bool )
	0x01 check-tag-primitive
	read-length 1 <> if ERR_X509_BAD_BOOLEAN fail then
	read8 0<> ;

\ Identify an elliptic curve: read the OID, then check it against the
\ known curve OID.
: read-curve-ID ( lim -- lim curve )
	read-OID ifnot ERR_X509_UNSUPPORTED fail then
	choice
		ansix9p256r1 eqOID uf 23 enduf
		ansix9p384r1 eqOID uf 24 enduf
		ansix9p521r1 eqOID uf 25 enduf
		ERR_X509_UNSUPPORTED fail
	endchoice ;

\ A convenient debug word: print the current data stack contents.
cc: DEBUG ( -- ) {
	extern int printf(const char *fmt, ...);
	uint32_t *p;

	printf("<stack:");
	for (p = &CTX->dp_stack[0]; p != dp; p ++) {
		printf(" %lu", (unsigned long)*p);
	}
	printf(" >\n");
}



( run in 2.470 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )