summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorjsing <>2019-09-08 17:00:05 +0000
committerjsing <>2019-09-08 17:00:05 +0000
commit79f43db0e9e6910673a15e03e802c3cc28083b8a (patch)
tree26ee5913af92445d851c4a009a9e9875b8ec536c /src
parent11474dfb0e4a1fb55d042fbfb4e2c68602f61508 (diff)
downloadopenbsd-79f43db0e9e6910673a15e03e802c3cc28083b8a.tar.gz
openbsd-79f43db0e9e6910673a15e03e802c3cc28083b8a.tar.bz2
openbsd-79f43db0e9e6910673a15e03e802c3cc28083b8a.zip
Add CMS ECC support.
This brings in EC code from OpenSSL 1.1.1b, with style(9) and whitespace cleanups. All of this code is currently under OPENSSL_NO_CMS hence is a no-op. ok inoguchi@
Diffstat (limited to 'src')
-rw-r--r--src/lib/libcrypto/ec/ec_ameth.c372
1 files changed, 370 insertions, 2 deletions
diff --git a/src/lib/libcrypto/ec/ec_ameth.c b/src/lib/libcrypto/ec/ec_ameth.c
index 04c068200f..a7e80c73d7 100644
--- a/src/lib/libcrypto/ec/ec_ameth.c
+++ b/src/lib/libcrypto/ec/ec_ameth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_ameth.c,v 1.25 2018/08/24 20:22:15 tb Exp $ */ 1/* $OpenBSD: ec_ameth.c,v 1.26 2019/09/08 17:00:05 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -65,9 +65,15 @@
65#include <openssl/err.h> 65#include <openssl/err.h>
66#include <openssl/x509.h> 66#include <openssl/x509.h>
67 67
68
69#include "asn1_locl.h" 68#include "asn1_locl.h"
70 69
70#ifndef OPENSSL_NO_CMS
71#include <openssl/cms.h>
72
73static int ecdh_cms_decrypt(CMS_RecipientInfo *ri);
74static int ecdh_cms_encrypt(CMS_RecipientInfo *ri);
75#endif
76
71static int 77static int
72eckey_param2type(int *pptype, void **ppval, EC_KEY * ec_key) 78eckey_param2type(int *pptype, void **ppval, EC_KEY * ec_key)
73{ 79{
@@ -573,6 +579,36 @@ ec_pkey_ctrl(EVP_PKEY * pkey, int op, long arg1, void *arg2)
573 } 579 }
574 return 1; 580 return 1;
575 581
582#ifndef OPENSSL_NO_CMS
583 case ASN1_PKEY_CTRL_CMS_SIGN:
584 if (arg1 == 0) {
585 X509_ALGOR *alg1, *alg2;
586 int snid, hnid;
587
588 CMS_SignerInfo_get0_algs(arg2, NULL, NULL, &alg1, &alg2);
589 if (alg1 == NULL || alg1->algorithm == NULL)
590 return -1;
591 hnid = OBJ_obj2nid(alg1->algorithm);
592 if (hnid == NID_undef)
593 return -1;
594 if (!OBJ_find_sigid_by_algs(&snid, hnid, EVP_PKEY_id(pkey)))
595 return -1;
596 X509_ALGOR_set0(alg2, OBJ_nid2obj(snid), V_ASN1_UNDEF, 0);
597 }
598 return 1;
599
600 case ASN1_PKEY_CTRL_CMS_ENVELOPE:
601 if (arg1 == 0)
602 return ecdh_cms_encrypt(arg2);
603 else if (arg1 == 1)
604 return ecdh_cms_decrypt(arg2);
605 return -2;
606
607 case ASN1_PKEY_CTRL_CMS_RI_TYPE:
608 *(int *)arg2 = CMS_RECIPINFO_AGREE;
609 return 1;
610#endif
611
576 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 612 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
577 *(int *) arg2 = NID_sha1; 613 *(int *) arg2 = NID_sha1;
578 return 2; 614 return 2;
@@ -584,6 +620,338 @@ ec_pkey_ctrl(EVP_PKEY * pkey, int op, long arg1, void *arg2)
584 620
585} 621}
586 622
623#ifndef OPENSSL_NO_CMS
624
625static int
626ecdh_cms_set_peerkey(EVP_PKEY_CTX *pctx, X509_ALGOR *alg,
627 ASN1_BIT_STRING *pubkey)
628{
629 const ASN1_OBJECT *aoid;
630 int atype;
631 const void *aval;
632 int rv = 0;
633 EVP_PKEY *pkpeer = NULL;
634 EC_KEY *ecpeer = NULL;
635 const unsigned char *p;
636 int plen;
637
638 X509_ALGOR_get0(&aoid, &atype, &aval, alg);
639 if (OBJ_obj2nid(aoid) != NID_X9_62_id_ecPublicKey)
640 goto err;
641
642 /* If absent parameters get group from main key */
643 if (atype == V_ASN1_UNDEF || atype == V_ASN1_NULL) {
644 const EC_GROUP *grp;
645 EVP_PKEY *pk;
646
647 pk = EVP_PKEY_CTX_get0_pkey(pctx);
648 if (!pk)
649 goto err;
650 grp = EC_KEY_get0_group(pk->pkey.ec);
651 ecpeer = EC_KEY_new();
652 if (ecpeer == NULL)
653 goto err;
654 if (!EC_KEY_set_group(ecpeer, grp))
655 goto err;
656 } else {
657 ecpeer = eckey_type2param(atype, aval);
658 if (!ecpeer)
659 goto err;
660 }
661
662 /* We have parameters now set public key */
663 plen = ASN1_STRING_length(pubkey);
664 p = ASN1_STRING_get0_data(pubkey);
665 if (!p || !plen)
666 goto err;
667 if (!o2i_ECPublicKey(&ecpeer, &p, plen))
668 goto err;
669 pkpeer = EVP_PKEY_new();
670 if (pkpeer == NULL)
671 goto err;
672 EVP_PKEY_set1_EC_KEY(pkpeer, ecpeer);
673 if (EVP_PKEY_derive_set_peer(pctx, pkpeer) > 0)
674 rv = 1;
675 err:
676 EC_KEY_free(ecpeer);
677 EVP_PKEY_free(pkpeer);
678 return rv;
679}
680
681/* Set KDF parameters based on KDF NID */
682static int
683ecdh_cms_set_kdf_param(EVP_PKEY_CTX *pctx, int eckdf_nid)
684{
685 int kdf_nid, kdfmd_nid, cofactor;
686 const EVP_MD *kdf_md;
687
688 if (eckdf_nid == NID_undef)
689 return 0;
690
691 /* Lookup KDF type, cofactor mode and digest */
692 if (!OBJ_find_sigid_algs(eckdf_nid, &kdfmd_nid, &kdf_nid))
693 return 0;
694
695 if (kdf_nid == NID_dh_std_kdf)
696 cofactor = 0;
697 else if (kdf_nid == NID_dh_cofactor_kdf)
698 cofactor = 1;
699 else
700 return 0;
701
702 if (EVP_PKEY_CTX_set_ecdh_cofactor_mode(pctx, cofactor) <= 0)
703 return 0;
704
705 if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, EVP_PKEY_ECDH_KDF_X9_63) <= 0)
706 return 0;
707
708 kdf_md = EVP_get_digestbynid(kdfmd_nid);
709 if (!kdf_md)
710 return 0;
711
712 if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
713 return 0;
714
715 return 1;
716}
717
718static int
719ecdh_cms_set_shared_info(EVP_PKEY_CTX *pctx, CMS_RecipientInfo *ri)
720{
721 X509_ALGOR *alg, *kekalg = NULL;
722 ASN1_OCTET_STRING *ukm;
723 const unsigned char *p;
724 unsigned char *der = NULL;
725 int plen, keylen;
726 const EVP_CIPHER *kekcipher;
727 EVP_CIPHER_CTX *kekctx;
728 int rv = 0;
729
730 if (!CMS_RecipientInfo_kari_get0_alg(ri, &alg, &ukm))
731 return 0;
732
733 if (!ecdh_cms_set_kdf_param(pctx, OBJ_obj2nid(alg->algorithm))) {
734 ECerror(EC_R_KDF_PARAMETER_ERROR);
735 return 0;
736 }
737
738 if (alg->parameter->type != V_ASN1_SEQUENCE)
739 return 0;
740
741 p = alg->parameter->value.sequence->data;
742 plen = alg->parameter->value.sequence->length;
743 kekalg = d2i_X509_ALGOR(NULL, &p, plen);
744 if (!kekalg)
745 goto err;
746 kekctx = CMS_RecipientInfo_kari_get0_ctx(ri);
747 if (!kekctx)
748 goto err;
749 kekcipher = EVP_get_cipherbyobj(kekalg->algorithm);
750 if (!kekcipher || EVP_CIPHER_mode(kekcipher) != EVP_CIPH_WRAP_MODE)
751 goto err;
752 if (!EVP_EncryptInit_ex(kekctx, kekcipher, NULL, NULL, NULL))
753 goto err;
754 if (EVP_CIPHER_asn1_to_param(kekctx, kekalg->parameter) <= 0)
755 goto err;
756
757 keylen = EVP_CIPHER_CTX_key_length(kekctx);
758 if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
759 goto err;
760
761 plen = CMS_SharedInfo_encode(&der, kekalg, ukm, keylen);
762 if (!plen)
763 goto err;
764
765 if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, der, plen) <= 0)
766 goto err;
767 der = NULL;
768
769 rv = 1;
770 err:
771 X509_ALGOR_free(kekalg);
772 free(der);
773 return rv;
774}
775
776static int
777ecdh_cms_decrypt(CMS_RecipientInfo *ri)
778{
779 EVP_PKEY_CTX *pctx;
780
781 pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
782 if (!pctx)
783 return 0;
784
785 /* See if we need to set peer key */
786 if (!EVP_PKEY_CTX_get0_peerkey(pctx)) {
787 X509_ALGOR *alg;
788 ASN1_BIT_STRING *pubkey;
789
790 if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &alg, &pubkey,
791 NULL, NULL, NULL))
792 return 0;
793 if (!alg || !pubkey)
794 return 0;
795 if (!ecdh_cms_set_peerkey(pctx, alg, pubkey)) {
796 ECerror(EC_R_PEER_KEY_ERROR);
797 return 0;
798 }
799 }
800
801 /* Set ECDH derivation parameters and initialise unwrap context */
802 if (!ecdh_cms_set_shared_info(pctx, ri)) {
803 ECerror(EC_R_SHARED_INFO_ERROR);
804 return 0;
805 }
806
807 return 1;
808}
809
810static int
811ecdh_cms_encrypt(CMS_RecipientInfo *ri)
812{
813 EVP_PKEY_CTX *pctx;
814 EVP_PKEY *pkey;
815 EVP_CIPHER_CTX *ctx;
816 int keylen;
817 X509_ALGOR *talg, *wrap_alg = NULL;
818 const ASN1_OBJECT *aoid;
819 ASN1_BIT_STRING *pubkey;
820 ASN1_STRING *wrap_str;
821 ASN1_OCTET_STRING *ukm;
822 unsigned char *penc = NULL;
823 int penclen;
824 int ecdh_nid, kdf_type, kdf_nid, wrap_nid;
825 const EVP_MD *kdf_md;
826 int rv = 0;
827
828 pctx = CMS_RecipientInfo_get0_pkey_ctx(ri);
829 if (!pctx)
830 return 0;
831 /* Get ephemeral key */
832 pkey = EVP_PKEY_CTX_get0_pkey(pctx);
833 if (!CMS_RecipientInfo_kari_get0_orig_id(ri, &talg, &pubkey,
834 NULL, NULL, NULL))
835 goto err;
836 X509_ALGOR_get0(&aoid, NULL, NULL, talg);
837
838 /* Is everything uninitialised? */
839 if (aoid == OBJ_nid2obj(NID_undef)) {
840 EC_KEY *eckey = pkey->pkey.ec;
841 unsigned char *p;
842
843 /* Set the key */
844 penclen = i2o_ECPublicKey(eckey, NULL);
845 if (penclen <= 0)
846 goto err;
847 penc = malloc(penclen);
848 if (penc == NULL)
849 goto err;
850 p = penc;
851 penclen = i2o_ECPublicKey(eckey, &p);
852 if (penclen <= 0)
853 goto err;
854 ASN1_STRING_set0(pubkey, penc, penclen);
855 pubkey->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07);
856 pubkey->flags |= ASN1_STRING_FLAG_BITS_LEFT;
857 penc = NULL;
858
859 X509_ALGOR_set0(talg, OBJ_nid2obj(NID_X9_62_id_ecPublicKey),
860 V_ASN1_UNDEF, NULL);
861 }
862
863 /* See if custom parameters set */
864 kdf_type = EVP_PKEY_CTX_get_ecdh_kdf_type(pctx);
865 if (kdf_type <= 0)
866 goto err;
867 if (!EVP_PKEY_CTX_get_ecdh_kdf_md(pctx, &kdf_md))
868 goto err;
869 ecdh_nid = EVP_PKEY_CTX_get_ecdh_cofactor_mode(pctx);
870 if (ecdh_nid < 0)
871 goto err;
872 else if (ecdh_nid == 0)
873 ecdh_nid = NID_dh_std_kdf;
874 else if (ecdh_nid == 1)
875 ecdh_nid = NID_dh_cofactor_kdf;
876
877 if (kdf_type == EVP_PKEY_ECDH_KDF_NONE) {
878 kdf_type = EVP_PKEY_ECDH_KDF_X9_63;
879 if (EVP_PKEY_CTX_set_ecdh_kdf_type(pctx, kdf_type) <= 0)
880 goto err;
881 } else {
882 /* Unknown KDF */
883 goto err;
884 }
885 if (kdf_md == NULL) {
886 /* Fixme later for better MD */
887 kdf_md = EVP_sha1();
888 if (EVP_PKEY_CTX_set_ecdh_kdf_md(pctx, kdf_md) <= 0)
889 goto err;
890 }
891
892 if (!CMS_RecipientInfo_kari_get0_alg(ri, &talg, &ukm))
893 goto err;
894
895 /* Lookup NID for KDF+cofactor+digest */
896 if (!OBJ_find_sigid_by_algs(&kdf_nid, EVP_MD_type(kdf_md), ecdh_nid))
897 goto err;
898
899 /* Get wrap NID */
900 ctx = CMS_RecipientInfo_kari_get0_ctx(ri);
901 wrap_nid = EVP_CIPHER_CTX_type(ctx);
902 keylen = EVP_CIPHER_CTX_key_length(ctx);
903
904 /* Package wrap algorithm in an AlgorithmIdentifier */
905
906 wrap_alg = X509_ALGOR_new();
907 if (wrap_alg == NULL)
908 goto err;
909 wrap_alg->algorithm = OBJ_nid2obj(wrap_nid);
910 wrap_alg->parameter = ASN1_TYPE_new();
911 if (wrap_alg->parameter == NULL)
912 goto err;
913 if (EVP_CIPHER_param_to_asn1(ctx, wrap_alg->parameter) <= 0)
914 goto err;
915 if (ASN1_TYPE_get(wrap_alg->parameter) == NID_undef) {
916 ASN1_TYPE_free(wrap_alg->parameter);
917 wrap_alg->parameter = NULL;
918 }
919
920 if (EVP_PKEY_CTX_set_ecdh_kdf_outlen(pctx, keylen) <= 0)
921 goto err;
922
923 penclen = CMS_SharedInfo_encode(&penc, wrap_alg, ukm, keylen);
924 if (!penclen)
925 goto err;
926
927 if (EVP_PKEY_CTX_set0_ecdh_kdf_ukm(pctx, penc, penclen) <= 0)
928 goto err;
929 penc = NULL;
930
931 /*
932 * Now need to wrap encoding of wrap AlgorithmIdentifier into parameter
933 * of another AlgorithmIdentifier.
934 */
935 penclen = i2d_X509_ALGOR(wrap_alg, &penc);
936 if (!penc || !penclen)
937 goto err;
938 wrap_str = ASN1_STRING_new();
939 if (wrap_str == NULL)
940 goto err;
941 ASN1_STRING_set0(wrap_str, penc, penclen);
942 penc = NULL;
943 X509_ALGOR_set0(talg, OBJ_nid2obj(kdf_nid), V_ASN1_SEQUENCE, wrap_str);
944
945 rv = 1;
946
947 err:
948 free(penc);
949 X509_ALGOR_free(wrap_alg);
950 return rv;
951}
952
953#endif
954
587const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = { 955const EVP_PKEY_ASN1_METHOD eckey_asn1_meth = {
588 .pkey_id = EVP_PKEY_EC, 956 .pkey_id = EVP_PKEY_EC,
589 .pkey_base_id = EVP_PKEY_EC, 957 .pkey_base_id = EVP_PKEY_EC,