diff options
author | beck <> | 2015-10-02 15:04:45 +0000 |
---|---|---|
committer | beck <> | 2015-10-02 15:04:45 +0000 |
commit | 61992d68f1934e7e4171e633f39fb76a4654b5a2 (patch) | |
tree | 8649498e5e9fdda4e44ebac5989504efbcc57b61 /src/lib/libcrypto/x509 | |
parent | 5951a0298417b41fc2a1fb4ad8a057fb9530e872 (diff) | |
download | openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.tar.gz openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.tar.bz2 openbsd-61992d68f1934e7e4171e633f39fb76a4654b5a2.zip |
Flense the greasy black guts of unreadble string parsing code out of three areas
in asn1 and x509 code, all dealing with an ASN1_TIME. This brings the parsing
together in one function that converts into a struct tm. While we are at it this
also brings us into conformance with RFC 5280 for times allowed in an X509 cert,
as OpenSSL is very liberal with what it allows.
input and fixes from deraadt@ jsing@ guethther@ and others.
ok krw@, guenther@, jsing@
Diffstat (limited to 'src/lib/libcrypto/x509')
-rw-r--r-- | src/lib/libcrypto/x509/x509_lcl.h | 1 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 128 |
2 files changed, 37 insertions, 92 deletions
diff --git a/src/lib/libcrypto/x509/x509_lcl.h b/src/lib/libcrypto/x509/x509_lcl.h index b16df78ad7..0c1c130d5c 100644 --- a/src/lib/libcrypto/x509/x509_lcl.h +++ b/src/lib/libcrypto/x509/x509_lcl.h | |||
@@ -57,3 +57,4 @@ | |||
57 | */ | 57 | */ |
58 | 58 | ||
59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); | 59 | int x509_check_cert_time(X509_STORE_CTX *ctx, X509 *x, int quiet); |
60 | int asn1_time_parse(const char *, size_t, struct tm *, int); | ||
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index 8d4d15668e..c48143f351 100644 --- a/src/lib/libcrypto/x509/x509_vfy.c +++ b/src/lib/libcrypto/x509/x509_vfy.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_vfy.c,v 1.45 2015/09/14 16:13:39 jsing Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.46 2015/10/02 15:04:45 beck Exp $ */ |
2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) | 2 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) |
3 | * All rights reserved. | 3 | * All rights reserved. |
4 | * | 4 | * |
@@ -1631,106 +1631,50 @@ X509_cmp_current_time(const ASN1_TIME *ctm) | |||
1631 | return X509_cmp_time(ctm, NULL); | 1631 | return X509_cmp_time(ctm, NULL); |
1632 | } | 1632 | } |
1633 | 1633 | ||
1634 | /* | ||
1635 | * Compare a possibly unvalidated ASN1_TIME string against a time_t | ||
1636 | * using RFC 5280 rules for the time string. If *cmp_time is NULL | ||
1637 | * the current system time is used. | ||
1638 | * | ||
1639 | * XXX NOTE that unlike what you expect a "cmp" function to do in C, | ||
1640 | * XXX this one is "special", and returns 0 for error. | ||
1641 | * | ||
1642 | * Returns: | ||
1643 | * -1 if the ASN1_time is earlier than OR the same as *cmp_time. | ||
1644 | * 1 if the ASN1_time is later than *cmp_time. | ||
1645 | * 0 on error. | ||
1646 | */ | ||
1634 | int | 1647 | int |
1635 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) | 1648 | X509_cmp_time(const ASN1_TIME *ctm, time_t *cmp_time) |
1636 | { | 1649 | { |
1637 | char *str; | 1650 | time_t time1, time2; |
1638 | ASN1_TIME atm; | 1651 | struct tm tm1; |
1639 | long offset; | 1652 | int ret = 0; |
1640 | char buff1[24], buff2[24], *p; | ||
1641 | int i, j; | ||
1642 | 1653 | ||
1643 | p = buff1; | 1654 | if (cmp_time == NULL) |
1644 | i = ctm->length; | 1655 | time2 = time(NULL); |
1645 | str = (char *)ctm->data; | 1656 | else |
1646 | if (ctm->type == V_ASN1_UTCTIME) { | 1657 | time2 = *cmp_time; |
1647 | if ((i < 11) || (i > 17)) | ||
1648 | return 0; | ||
1649 | memcpy(p, str, 10); | ||
1650 | p += 10; | ||
1651 | str += 10; | ||
1652 | i -= 10; | ||
1653 | } else { | ||
1654 | if (i < 13) | ||
1655 | return 0; | ||
1656 | memcpy(p, str, 12); | ||
1657 | p += 12; | ||
1658 | str += 12; | ||
1659 | i -= 12; | ||
1660 | } | ||
1661 | 1658 | ||
1662 | if (i < 1) | 1659 | memset(&tm1, 0, sizeof(tm1)); |
1663 | return 0; | ||
1664 | if ((*str == 'Z') || (*str == '-') || (*str == '+')) { | ||
1665 | *(p++) = '0'; | ||
1666 | *(p++) = '0'; | ||
1667 | } else { | ||
1668 | if (i < 2) | ||
1669 | return 0; | ||
1670 | *(p++) = *(str++); | ||
1671 | *(p++) = *(str++); | ||
1672 | i -= 2; | ||
1673 | if (i < 1) | ||
1674 | return 0; | ||
1675 | /* Skip any fractional seconds... */ | ||
1676 | if (*str == '.') { | ||
1677 | str++; | ||
1678 | i--; | ||
1679 | while (i > 1 && (*str >= '0') && (*str <= '9')) { | ||
1680 | str++; | ||
1681 | i--; | ||
1682 | } | ||
1683 | } | ||
1684 | } | ||
1685 | *(p++) = 'Z'; | ||
1686 | *(p++) = '\0'; | ||
1687 | 1660 | ||
1688 | if (i < 1) | 1661 | if (asn1_time_parse(ctm->data, ctm->length, &tm1, 0) == -1) |
1689 | return 0; | 1662 | goto out; /* invalid time */ |
1690 | if (*str == 'Z') { | ||
1691 | if (i != 1) | ||
1692 | return 0; | ||
1693 | offset = 0; | ||
1694 | } else { | ||
1695 | if (i != 5) | ||
1696 | return 0; | ||
1697 | if ((*str != '+') && (*str != '-')) | ||
1698 | return 0; | ||
1699 | if (str[1] < '0' || str[1] > '9' || | ||
1700 | str[2] < '0' || str[2] > '9' || | ||
1701 | str[3] < '0' || str[3] > '9' || | ||
1702 | str[4] < '0' || str[4] > '9') | ||
1703 | return 0; | ||
1704 | offset = ((str[1] - '0') * 10 + (str[2] - '0')) * 60; | ||
1705 | offset += (str[3] - '0') * 10 + (str[4] - '0'); | ||
1706 | if (*str == '-') | ||
1707 | offset = -offset; | ||
1708 | } | ||
1709 | atm.type = ctm->type; | ||
1710 | atm.flags = 0; | ||
1711 | atm.length = sizeof(buff2); | ||
1712 | atm.data = (unsigned char *)buff2; | ||
1713 | 1663 | ||
1714 | if (X509_time_adj(&atm, offset * 60, cmp_time) == NULL) | 1664 | /* |
1715 | return 0; | 1665 | * Defensively fail if the time string is not representable as |
1666 | * a time_t. A time_t must be sane if you care about times after | ||
1667 | * Jan 19 2038. | ||
1668 | */ | ||
1669 | if ((time1 = timegm(&tm1)) == -1) | ||
1670 | goto out; | ||
1716 | 1671 | ||
1717 | if (ctm->type == V_ASN1_UTCTIME) { | 1672 | if (time1 <= time2) |
1718 | i = (buff1[0] - '0') * 10 + (buff1[1] - '0'); | 1673 | ret = -1; |
1719 | if (i < 50) | ||
1720 | i += 100; /* cf. RFC 2459 */ | ||
1721 | j = (buff2[0] - '0') * 10 + (buff2[1] - '0'); | ||
1722 | if (j < 50) | ||
1723 | j += 100; | ||
1724 | if (i < j) | ||
1725 | return -1; | ||
1726 | if (i > j) | ||
1727 | return 1; | ||
1728 | } | ||
1729 | i = strcmp(buff1, buff2); | ||
1730 | if (i == 0) /* wait a second then return younger :-) */ | ||
1731 | return -1; | ||
1732 | else | 1674 | else |
1733 | return i; | 1675 | ret = 1; |
1676 | out: | ||
1677 | return (ret); | ||
1734 | } | 1678 | } |
1735 | 1679 | ||
1736 | ASN1_TIME * | 1680 | ASN1_TIME * |