diff options
Diffstat (limited to 'src/lib/libcrypto/x509v3/v3_utl.c')
| -rw-r--r-- | src/lib/libcrypto/x509v3/v3_utl.c | 343 |
1 files changed, 338 insertions, 5 deletions
diff --git a/src/lib/libcrypto/x509v3/v3_utl.c b/src/lib/libcrypto/x509v3/v3_utl.c index f23a8d29a0..57be441399 100644 --- a/src/lib/libcrypto/x509v3/v3_utl.c +++ b/src/lib/libcrypto/x509v3/v3_utl.c | |||
| @@ -1,9 +1,9 @@ | |||
| 1 | /* v3_utl.c */ | 1 | /* v3_utl.c */ |
| 2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL |
| 3 | * project 1999. | 3 | * project. |
| 4 | */ | 4 | */ |
| 5 | /* ==================================================================== | 5 | /* ==================================================================== |
| 6 | * Copyright (c) 1999 The OpenSSL Project. All rights reserved. | 6 | * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| 9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions |
| @@ -63,6 +63,7 @@ | |||
| 63 | #include "cryptlib.h" | 63 | #include "cryptlib.h" |
| 64 | #include <openssl/conf.h> | 64 | #include <openssl/conf.h> |
| 65 | #include <openssl/x509v3.h> | 65 | #include <openssl/x509v3.h> |
| 66 | #include <openssl/bn.h> | ||
| 66 | 67 | ||
| 67 | static char *strip_spaces(char *name); | 68 | static char *strip_spaces(char *name); |
| 68 | static int sk_strcmp(const char * const *a, const char * const *b); | 69 | static int sk_strcmp(const char * const *a, const char * const *b); |
| @@ -70,6 +71,11 @@ static STACK *get_email(X509_NAME *name, GENERAL_NAMES *gens); | |||
| 70 | static void str_free(void *str); | 71 | static void str_free(void *str); |
| 71 | static int append_ia5(STACK **sk, ASN1_IA5STRING *email); | 72 | static int append_ia5(STACK **sk, ASN1_IA5STRING *email); |
| 72 | 73 | ||
| 74 | static int ipv4_from_asc(unsigned char *v4, const char *in); | ||
| 75 | static int ipv6_from_asc(unsigned char *v6, const char *in); | ||
| 76 | static int ipv6_cb(const char *elem, int len, void *usr); | ||
| 77 | static int ipv6_hex(unsigned char *out, const char *in, int inlen); | ||
| 78 | |||
| 73 | /* Add a CONF_VALUE name value pair to stack */ | 79 | /* Add a CONF_VALUE name value pair to stack */ |
| 74 | 80 | ||
| 75 | int X509V3_add_value(const char *name, const char *value, | 81 | int X509V3_add_value(const char *name, const char *value, |
| @@ -156,11 +162,11 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) | |||
| 156 | ASN1_INTEGER *aint; | 162 | ASN1_INTEGER *aint; |
| 157 | int isneg, ishex; | 163 | int isneg, ishex; |
| 158 | int ret; | 164 | int ret; |
| 159 | bn = BN_new(); | ||
| 160 | if (!value) { | 165 | if (!value) { |
| 161 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); | 166 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_INVALID_NULL_VALUE); |
| 162 | return 0; | 167 | return 0; |
| 163 | } | 168 | } |
| 169 | bn = BN_new(); | ||
| 164 | if (value[0] == '-') { | 170 | if (value[0] == '-') { |
| 165 | value++; | 171 | value++; |
| 166 | isneg = 1; | 172 | isneg = 1; |
| @@ -174,7 +180,8 @@ ASN1_INTEGER *s2i_ASN1_INTEGER(X509V3_EXT_METHOD *method, char *value) | |||
| 174 | if (ishex) ret = BN_hex2bn(&bn, value); | 180 | if (ishex) ret = BN_hex2bn(&bn, value); |
| 175 | else ret = BN_dec2bn(&bn, value); | 181 | else ret = BN_dec2bn(&bn, value); |
| 176 | 182 | ||
| 177 | if (!ret) { | 183 | if (!ret || value[ret]) { |
| 184 | BN_free(bn); | ||
| 178 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); | 185 | X509V3err(X509V3_F_S2I_ASN1_INTEGER,X509V3_R_BN_DEC2BN_ERROR); |
| 179 | return 0; | 186 | return 0; |
| 180 | } | 187 | } |
| @@ -358,7 +365,7 @@ char *hex_to_string(unsigned char *buffer, long len) | |||
| 358 | char *tmp, *q; | 365 | char *tmp, *q; |
| 359 | unsigned char *p; | 366 | unsigned char *p; |
| 360 | int i; | 367 | int i; |
| 361 | static char hexdig[] = "0123456789ABCDEF"; | 368 | const static char hexdig[] = "0123456789ABCDEF"; |
| 362 | if(!buffer || !len) return NULL; | 369 | if(!buffer || !len) return NULL; |
| 363 | if(!(tmp = OPENSSL_malloc(len * 3 + 1))) { | 370 | if(!(tmp = OPENSSL_malloc(len * 3 + 1))) { |
| 364 | X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); | 371 | X509V3err(X509V3_F_HEX_TO_STRING,ERR_R_MALLOC_FAILURE); |
| @@ -466,6 +473,30 @@ STACK *X509_get1_email(X509 *x) | |||
| 466 | return ret; | 473 | return ret; |
| 467 | } | 474 | } |
| 468 | 475 | ||
| 476 | STACK *X509_get1_ocsp(X509 *x) | ||
| 477 | { | ||
| 478 | AUTHORITY_INFO_ACCESS *info; | ||
| 479 | STACK *ret = NULL; | ||
| 480 | int i; | ||
| 481 | info = X509_get_ext_d2i(x, NID_info_access, NULL, NULL); | ||
| 482 | if (!info) | ||
| 483 | return NULL; | ||
| 484 | for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) | ||
| 485 | { | ||
| 486 | ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i); | ||
| 487 | if (OBJ_obj2nid(ad->method) == NID_ad_OCSP) | ||
| 488 | { | ||
| 489 | if (ad->location->type == GEN_URI) | ||
| 490 | { | ||
| 491 | if (!append_ia5(&ret, ad->location->d.uniformResourceIdentifier)) | ||
| 492 | break; | ||
| 493 | } | ||
| 494 | } | ||
| 495 | } | ||
| 496 | AUTHORITY_INFO_ACCESS_free(info); | ||
| 497 | return ret; | ||
| 498 | } | ||
| 499 | |||
| 469 | STACK *X509_REQ_get1_email(X509_REQ *x) | 500 | STACK *X509_REQ_get1_email(X509_REQ *x) |
| 470 | { | 501 | { |
| 471 | GENERAL_NAMES *gens; | 502 | GENERAL_NAMES *gens; |
| @@ -533,3 +564,305 @@ void X509_email_free(STACK *sk) | |||
| 533 | { | 564 | { |
| 534 | sk_pop_free(sk, str_free); | 565 | sk_pop_free(sk, str_free); |
| 535 | } | 566 | } |
| 567 | |||
| 568 | /* Convert IP addresses both IPv4 and IPv6 into an | ||
| 569 | * OCTET STRING compatible with RFC3280. | ||
| 570 | */ | ||
| 571 | |||
| 572 | ASN1_OCTET_STRING *a2i_IPADDRESS(const char *ipasc) | ||
| 573 | { | ||
| 574 | unsigned char ipout[16]; | ||
| 575 | ASN1_OCTET_STRING *ret; | ||
| 576 | int iplen; | ||
| 577 | |||
| 578 | /* If string contains a ':' assume IPv6 */ | ||
| 579 | |||
| 580 | iplen = a2i_ipadd(ipout, ipasc); | ||
| 581 | |||
| 582 | if (!iplen) | ||
| 583 | return NULL; | ||
| 584 | |||
| 585 | ret = ASN1_OCTET_STRING_new(); | ||
| 586 | if (!ret) | ||
| 587 | return NULL; | ||
| 588 | if (!ASN1_OCTET_STRING_set(ret, ipout, iplen)) | ||
| 589 | { | ||
| 590 | ASN1_OCTET_STRING_free(ret); | ||
| 591 | return NULL; | ||
| 592 | } | ||
| 593 | return ret; | ||
| 594 | } | ||
| 595 | |||
| 596 | ASN1_OCTET_STRING *a2i_IPADDRESS_NC(const char *ipasc) | ||
| 597 | { | ||
| 598 | ASN1_OCTET_STRING *ret = NULL; | ||
| 599 | unsigned char ipout[32]; | ||
| 600 | char *iptmp = NULL, *p; | ||
| 601 | int iplen1, iplen2; | ||
| 602 | p = strchr(ipasc,'/'); | ||
| 603 | if (!p) | ||
| 604 | return NULL; | ||
| 605 | iptmp = BUF_strdup(ipasc); | ||
| 606 | if (!iptmp) | ||
| 607 | return NULL; | ||
| 608 | p = iptmp + (p - ipasc); | ||
| 609 | *p++ = 0; | ||
| 610 | |||
| 611 | iplen1 = a2i_ipadd(ipout, iptmp); | ||
| 612 | |||
| 613 | if (!iplen1) | ||
| 614 | goto err; | ||
| 615 | |||
| 616 | iplen2 = a2i_ipadd(ipout + iplen1, p); | ||
| 617 | |||
| 618 | OPENSSL_free(iptmp); | ||
| 619 | iptmp = NULL; | ||
| 620 | |||
| 621 | if (!iplen2 || (iplen1 != iplen2)) | ||
| 622 | goto err; | ||
| 623 | |||
| 624 | ret = ASN1_OCTET_STRING_new(); | ||
| 625 | if (!ret) | ||
| 626 | goto err; | ||
| 627 | if (!ASN1_OCTET_STRING_set(ret, ipout, iplen1 + iplen2)) | ||
| 628 | goto err; | ||
| 629 | |||
| 630 | return ret; | ||
| 631 | |||
| 632 | err: | ||
| 633 | if (iptmp) | ||
| 634 | OPENSSL_free(iptmp); | ||
| 635 | if (ret) | ||
| 636 | ASN1_OCTET_STRING_free(ret); | ||
| 637 | return NULL; | ||
| 638 | } | ||
| 639 | |||
| 640 | |||
| 641 | int a2i_ipadd(unsigned char *ipout, const char *ipasc) | ||
| 642 | { | ||
| 643 | /* If string contains a ':' assume IPv6 */ | ||
| 644 | |||
| 645 | if (strchr(ipasc, ':')) | ||
| 646 | { | ||
| 647 | if (!ipv6_from_asc(ipout, ipasc)) | ||
| 648 | return 0; | ||
| 649 | return 16; | ||
| 650 | } | ||
| 651 | else | ||
| 652 | { | ||
| 653 | if (!ipv4_from_asc(ipout, ipasc)) | ||
| 654 | return 0; | ||
| 655 | return 4; | ||
| 656 | } | ||
| 657 | } | ||
| 658 | |||
| 659 | static int ipv4_from_asc(unsigned char *v4, const char *in) | ||
| 660 | { | ||
| 661 | int a0, a1, a2, a3; | ||
| 662 | if (sscanf(in, "%d.%d.%d.%d", &a0, &a1, &a2, &a3) != 4) | ||
| 663 | return 0; | ||
| 664 | if ((a0 < 0) || (a0 > 255) || (a1 < 0) || (a1 > 255) | ||
| 665 | || (a2 < 0) || (a2 > 255) || (a3 < 0) || (a3 > 255)) | ||
| 666 | return 0; | ||
| 667 | v4[0] = a0; | ||
| 668 | v4[1] = a1; | ||
| 669 | v4[2] = a2; | ||
| 670 | v4[3] = a3; | ||
| 671 | return 1; | ||
| 672 | } | ||
| 673 | |||
| 674 | typedef struct { | ||
| 675 | /* Temporary store for IPV6 output */ | ||
| 676 | unsigned char tmp[16]; | ||
| 677 | /* Total number of bytes in tmp */ | ||
| 678 | int total; | ||
| 679 | /* The position of a zero (corresponding to '::') */ | ||
| 680 | int zero_pos; | ||
| 681 | /* Number of zeroes */ | ||
| 682 | int zero_cnt; | ||
| 683 | } IPV6_STAT; | ||
| 684 | |||
| 685 | |||
| 686 | static int ipv6_from_asc(unsigned char *v6, const char *in) | ||
| 687 | { | ||
| 688 | IPV6_STAT v6stat; | ||
| 689 | v6stat.total = 0; | ||
| 690 | v6stat.zero_pos = -1; | ||
| 691 | v6stat.zero_cnt = 0; | ||
| 692 | /* Treat the IPv6 representation as a list of values | ||
| 693 | * separated by ':'. The presence of a '::' will parse | ||
| 694 | * as one, two or three zero length elements. | ||
| 695 | */ | ||
| 696 | if (!CONF_parse_list(in, ':', 0, ipv6_cb, &v6stat)) | ||
| 697 | return 0; | ||
| 698 | |||
| 699 | /* Now for some sanity checks */ | ||
| 700 | |||
| 701 | if (v6stat.zero_pos == -1) | ||
| 702 | { | ||
| 703 | /* If no '::' must have exactly 16 bytes */ | ||
| 704 | if (v6stat.total != 16) | ||
| 705 | return 0; | ||
| 706 | } | ||
| 707 | else | ||
| 708 | { | ||
| 709 | /* If '::' must have less than 16 bytes */ | ||
| 710 | if (v6stat.total == 16) | ||
| 711 | return 0; | ||
| 712 | /* More than three zeroes is an error */ | ||
| 713 | if (v6stat.zero_cnt > 3) | ||
| 714 | return 0; | ||
| 715 | /* Can only have three zeroes if nothing else present */ | ||
| 716 | else if (v6stat.zero_cnt == 3) | ||
| 717 | { | ||
| 718 | if (v6stat.total > 0) | ||
| 719 | return 0; | ||
| 720 | } | ||
| 721 | /* Can only have two zeroes if at start or end */ | ||
| 722 | else if (v6stat.zero_cnt == 2) | ||
| 723 | { | ||
| 724 | if ((v6stat.zero_pos != 0) | ||
| 725 | && (v6stat.zero_pos != v6stat.total)) | ||
| 726 | return 0; | ||
| 727 | } | ||
| 728 | else | ||
| 729 | /* Can only have one zero if *not* start or end */ | ||
| 730 | { | ||
| 731 | if ((v6stat.zero_pos == 0) | ||
| 732 | || (v6stat.zero_pos == v6stat.total)) | ||
| 733 | return 0; | ||
| 734 | } | ||
| 735 | } | ||
| 736 | |||
| 737 | /* Format result */ | ||
| 738 | |||
| 739 | /* Copy initial part */ | ||
| 740 | if (v6stat.zero_pos > 0) | ||
| 741 | memcpy(v6, v6stat.tmp, v6stat.zero_pos); | ||
| 742 | /* Zero middle */ | ||
| 743 | if (v6stat.total != 16) | ||
| 744 | memset(v6 + v6stat.zero_pos, 0, 16 - v6stat.total); | ||
| 745 | /* Copy final part */ | ||
| 746 | if (v6stat.total != v6stat.zero_pos) | ||
| 747 | memcpy(v6 + v6stat.zero_pos + 16 - v6stat.total, | ||
| 748 | v6stat.tmp + v6stat.zero_pos, | ||
| 749 | v6stat.total - v6stat.zero_pos); | ||
| 750 | |||
| 751 | return 1; | ||
| 752 | } | ||
| 753 | |||
| 754 | static int ipv6_cb(const char *elem, int len, void *usr) | ||
| 755 | { | ||
| 756 | IPV6_STAT *s = usr; | ||
| 757 | /* Error if 16 bytes written */ | ||
| 758 | if (s->total == 16) | ||
| 759 | return 0; | ||
| 760 | if (len == 0) | ||
| 761 | { | ||
| 762 | /* Zero length element, corresponds to '::' */ | ||
| 763 | if (s->zero_pos == -1) | ||
| 764 | s->zero_pos = s->total; | ||
| 765 | /* If we've already got a :: its an error */ | ||
| 766 | else if (s->zero_pos != s->total) | ||
| 767 | return 0; | ||
| 768 | s->zero_cnt++; | ||
| 769 | } | ||
| 770 | else | ||
| 771 | { | ||
| 772 | /* If more than 4 characters could be final a.b.c.d form */ | ||
| 773 | if (len > 4) | ||
| 774 | { | ||
| 775 | /* Need at least 4 bytes left */ | ||
| 776 | if (s->total > 12) | ||
| 777 | return 0; | ||
| 778 | /* Must be end of string */ | ||
| 779 | if (elem[len]) | ||
| 780 | return 0; | ||
| 781 | if (!ipv4_from_asc(s->tmp + s->total, elem)) | ||
| 782 | return 0; | ||
| 783 | s->total += 4; | ||
| 784 | } | ||
| 785 | else | ||
| 786 | { | ||
| 787 | if (!ipv6_hex(s->tmp + s->total, elem, len)) | ||
| 788 | return 0; | ||
| 789 | s->total += 2; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | return 1; | ||
| 793 | } | ||
| 794 | |||
| 795 | /* Convert a string of up to 4 hex digits into the corresponding | ||
| 796 | * IPv6 form. | ||
| 797 | */ | ||
| 798 | |||
| 799 | static int ipv6_hex(unsigned char *out, const char *in, int inlen) | ||
| 800 | { | ||
| 801 | unsigned char c; | ||
| 802 | unsigned int num = 0; | ||
| 803 | if (inlen > 4) | ||
| 804 | return 0; | ||
| 805 | while(inlen--) | ||
| 806 | { | ||
| 807 | c = *in++; | ||
| 808 | num <<= 4; | ||
| 809 | if ((c >= '0') && (c <= '9')) | ||
| 810 | num |= c - '0'; | ||
| 811 | else if ((c >= 'A') && (c <= 'F')) | ||
| 812 | num |= c - 'A' + 10; | ||
| 813 | else if ((c >= 'a') && (c <= 'f')) | ||
| 814 | num |= c - 'a' + 10; | ||
| 815 | else | ||
| 816 | return 0; | ||
| 817 | } | ||
| 818 | out[0] = num >> 8; | ||
| 819 | out[1] = num & 0xff; | ||
| 820 | return 1; | ||
| 821 | } | ||
| 822 | |||
| 823 | |||
| 824 | int X509V3_NAME_from_section(X509_NAME *nm, STACK_OF(CONF_VALUE)*dn_sk, | ||
| 825 | unsigned long chtype) | ||
| 826 | { | ||
| 827 | CONF_VALUE *v; | ||
| 828 | int i, mval; | ||
| 829 | char *p, *type; | ||
| 830 | if (!nm) | ||
| 831 | return 0; | ||
| 832 | |||
| 833 | for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) | ||
| 834 | { | ||
| 835 | v=sk_CONF_VALUE_value(dn_sk,i); | ||
| 836 | type=v->name; | ||
| 837 | /* Skip past any leading X. X: X, etc to allow for | ||
| 838 | * multiple instances | ||
| 839 | */ | ||
| 840 | for(p = type; *p ; p++) | ||
| 841 | #ifndef CHARSET_EBCDIC | ||
| 842 | if ((*p == ':') || (*p == ',') || (*p == '.')) | ||
| 843 | #else | ||
| 844 | if ((*p == os_toascii[':']) || (*p == os_toascii[',']) || (*p == os_toascii['.'])) | ||
| 845 | #endif | ||
| 846 | { | ||
| 847 | p++; | ||
| 848 | if(*p) type = p; | ||
| 849 | break; | ||
| 850 | } | ||
| 851 | #ifndef CHARSET_EBCDIC | ||
| 852 | if (*type == '+') | ||
| 853 | #else | ||
| 854 | if (*type == os_toascii['+']) | ||
| 855 | #endif | ||
| 856 | { | ||
| 857 | mval = -1; | ||
| 858 | type++; | ||
| 859 | } | ||
| 860 | else | ||
| 861 | mval = 0; | ||
| 862 | if (!X509_NAME_add_entry_by_txt(nm,type, chtype, | ||
| 863 | (unsigned char *) v->value,-1,-1,mval)) | ||
| 864 | return 0; | ||
| 865 | |||
| 866 | } | ||
| 867 | return 1; | ||
| 868 | } | ||
