diff --git a/integration_tests/cli/pki-add-vid-scoped-x509-certificates.sh b/integration_tests/cli/pki-add-vid-scoped-x509-certificates.sh new file mode 100755 index 000000000..f271da010 --- /dev/null +++ b/integration_tests/cli/pki-add-vid-scoped-x509-certificates.sh @@ -0,0 +1,119 @@ +set -euo pipefail +source integration_tests/cli/common.sh + +root_cert_subject="MIGYMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjE=" +root_cert_subject_key_id="CE:A8:92:66:EA:E0:80:BD:2B:B5:68:E4:0B:07:C4:FA:2C:34:6D:31" +root_cert_path="integration_tests/constants/root_cert_with_vid" +root_cert_vid=65521 +intermediate_cert_subject="MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" +intermediate_cert_subject_key_id="0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" +intermediate_cert_1_path="integration_tests/constants/intermediate_cert_with_vid_1" +intermediate_cert_2_path="integration_tests/constants/intermediate_cert_with_vid_2" +intermediate_cert_1_serial_number="3" +intermediate_cert_2_serial_number="4" +intermediate_cert_1_vid=65521 +intermediate_cert_2_vid=65522 + +paa_cert_with_no_vid_path="integration_tests/constants/paa_cert_no_vid" +paa_cert_with_no_vid_subject="MBoxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQQ==" +paa_cert_with_no_vid_subject_key_id="78:5C:E7:05:B8:6B:8F:4E:6F:C7:93:AA:60:CB:43:EA:69:68:82:D5" +pai_cert_with_numeric_vid_path="integration_tests/constants/pai_cert_numeric_vid" +pai_cert_with_numeric_vid_subject="MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjI=" +pai_cert_with_numeric_vid_subject_key_id="61:3D:D0:87:35:5E:F0:8B:AE:01:E4:C6:9A:8F:C7:3D:AC:8C:7D:FD" +pai_cert_with_numeric_vid_vid=65522 +pai_cert_with_numeric_vid_serial_number="4428370313154203676" + +trustee_account="jack" +second_trustee_account="alice" + +test_divider + +echo "ADD VID SCOPED X509 CERTIFICATES" + +vendor_vid_65521=$root_cert_vid +vendor_account_65521=vendor_account_$vendor_vid_65521 +echo "Create Vendor account - $vendor_account_65521" +create_new_vendor_account $vendor_account_65521 $vendor_vid_65521 + +echo "Propose and approve root certificate with vid=$root_cert_vid" +result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$root_cert_path" --vid "$root_cert_vid" --from $trustee_account --yes) +check_response "$result" "\"code\": 0" +result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject="$root_cert_subject" --subject-key-id="$root_cert_subject_key_id" --from $second_trustee_account --yes) +check_response "$result" "\"code\": 0" + +echo "Add an intermediate certificate with vid=$intermediate_cert_1_vid by $vendor_account_65521 with vid=$vendor_vid_65521" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_1_path" --from $vendor_account_65521 --yes) +check_response "$result" "\"code\": 0" + +echo "Request all approved root certificates." +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" + +echo "Try to add an intermediate certificate with vid=$intermediate_cert_2_vid by $vendor_account_65521 with vid=$vendor_vid_65521" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$intermediate_cert_2_path" --from $vendor_account_65521 --yes) +check_response "$result" "\"code\": 440" + +echo "Request all approved root certificates should not contain intermediate cert with serialNumber=$intermediate_cert_2_serial_number" +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" +response_does_not_contain "$result" "\"serialNumber\": \"$intermediate_cert_2_serial_number\"" + +echo "Propose and approve non-vid root certificate" +result=$(echo "$passphrase" | dcld tx pki propose-add-x509-root-cert --certificate="$paa_cert_with_no_vid_path" --vid "65522" --from $trustee_account --yes) +check_response "$result" "\"code\": 0" +result=$(echo "$passphrase" | dcld tx pki approve-add-x509-root-cert --subject="$paa_cert_with_no_vid_subject" --subject-key-id="$paa_cert_with_no_vid_subject_key_id" --from $second_trustee_account --yes) +check_response "$result" "\"code\": 0" + +vendor_vid_65523=65523 +vendor_account_65523=vendor_account_$vendor_vid_65523 +echo "Create Vendor account - $vendor_account_65523" +create_new_vendor_account $vendor_account_65523 $vendor_vid_65523 + +echo "Add an intermediate certificate with vid=$pai_cert_with_numeric_vid_vid by $vendor_account_65523 with vid=$vendor_vid_65523" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$pai_cert_with_numeric_vid_path" --from $vendor_account_65523 --yes) +check_response "$result" "\"code\": 439" + +echo "Request all approved root certificates should not contain intermediate cert with serialNumber=$pai_cert_with_numeric_vid_serial_number" +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" +response_does_not_contain "$result" "\"subject\": \"$pai_cert_with_numeric_vid_subject\"" +response_does_not_contain "$result" "\"subjectKeyId\": \"$pai_cert_with_numeric_vid_subject_key_id" +response_does_not_contain "$result" "\"serialNumber\": \"$pai_cert_with_numeric_vid_serial_number\"" + +vendor_vid_65522=65522 +vendor_account_65522=vendor_account_$vendor_vid_65522 +echo "Create Vendor account - $vendor_account_65522" +create_new_vendor_account $vendor_account_65522 $vendor_vid_65522 + +echo "Add an intermediate certificate with vid=$pai_cert_with_numeric_vid_vid by $vendor_account_65522 with vid=$vendor_vid_65522" +result=$(echo "$passphrase" | dcld tx pki add-x509-cert --certificate="$pai_cert_with_numeric_vid_path" --from $vendor_account_65522 --yes) +check_response "$result" "\"code\": 0" + +echo "Request all approved root certificates should contain intermediate cert with serialNumber=$pai_cert_with_numeric_vid_serial_number" +result=$(dcld query pki all-x509-certs) +echo $result | jq +check_response "$result" "\"subject\": \"$root_cert_subject\"" +check_response "$result" "\"subject\": \"$intermediate_cert_subject\"" +check_response "$result" "\"subjectKeyId\": \"$root_cert_subject_key_id\"" +check_response "$result" "\"subjectKeyId\": \"$intermediate_cert_subject_key_id\"" +check_response "$result" "\"serialNumber\": \"$intermediate_cert_1_serial_number\"" +check_response "$result" "\"subject\": \"$pai_cert_with_numeric_vid_subject\"" +check_response "$result" "\"subjectKeyId\": \"$pai_cert_with_numeric_vid_subject_key_id" +check_response "$result" "\"serialNumber\": \"$pai_cert_with_numeric_vid_serial_number\"" + +test_divider diff --git a/integration_tests/constants/constants.go b/integration_tests/constants/constants.go index bd27ade14..b494f8c33 100644 --- a/integration_tests/constants/constants.go +++ b/integration_tests/constants/constants.go @@ -315,8 +315,11 @@ CU3r1RXsbs8zuBEVIl8yUogwHwYDVR0jBBgwFoAUav0idx9RH+y/FkGXZxDc3DGh cX4wCgYIKoZIzj0EAwIDSAAwRQIhAJbJyM8uAYhgBdj1vHLAe3X9mldpWsSRETET i+oDPOUDAiAlVJQ75X1T1sR199I+v8/CA2zSm6Y5PsfvrYcUq3GCGQ== -----END CERTIFICATE-----` - PAICertWithNumericPidVidVid = 65521 - PAICertWithNumericPidVidPid = 32768 + + PAICertWithNumericPidVidSubject = "MEYxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDAQ4MDAw" + PAICertWithNumericPidVidSubjectKeyID = "AF:42:B7:09:4D:EB:D5:15:EC:6E:CF:33:B8:11:15:22:5F:32:52:88" + PAICertWithNumericPidVidVid = 65521 + PAICertWithNumericPidVidPid = 32768 PAICertWithPidVid = ` -----BEGIN CERTIFICATE----- @@ -346,6 +349,9 @@ Q+ppaILVMAoGCCqGSM49BAMCA0gAMEUCIQDfwJ3oS/qVbWDW/vTirREL3iIqMogw pn4/F7keUYUaeAIgce2XGOSIsrjPlUQ1zj/zLqUFVhQ8TyycBaIK8z7Uytk= -----END CERTIFICATE-----` + PAICertWithNumericVidSubject = "MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBSTEUMBIGCisGAQQBgqJ8AgEMBEZGRjI=" + PAICertWithNumericVidSubjectKeyID = "61:3D:D0:87:35:5E:F0:8B:AE:01:E4:C6:9A:8F:C7:3D:AC:8C:7D:FD" + PAICertWithVid = `-----BEGIN CERTIFICATE----- MIIBmzCCAUKgAwIBAgIIIt8JcSeGaqMwCgYIKoZIzj0EAwIwGjEYMBYGA1UEAwwP TWF0dGVyIFRlc3QgUEFBMCAXDTIxMDYyODE0MjM0M1oYDzk5OTkxMjMxMjM1OTU5 @@ -439,6 +445,7 @@ p6lc3hTEQsQZsUwVzH74wu+whWZdKHHrEY7rONc/QiLmwZl+w2nGs+S62z20GueU XSNIRw5NvAwLCvnog8A47MIqpuF211kdKvu2QFM/ekMvduL8BpkIFVKULSOY1t9d XPz2ZlXABob+/ovGOyGPDw/3tUmlBXU= -----END CERTIFICATE-----` + RootCertWithSameSubjectAndSKID2 = `-----BEGIN CERTIFICATE----- MIID0zCCArugAwIBAgIBAjANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMx ETAPBgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwP @@ -462,6 +469,7 @@ BQADggEBAENwaLKvyNz0IW1BNH2eTYNvgFl4f/I1pVYPOlA0O0ZB4BupqtgfKdTF XWQLy4RZmLIkrm7vj3uFWRpi7lOBkAPOgCm04RTYqJJwnI0UeJmvaxoFd42J+k3D xEsSrRoqMgkOX01+kkNn8Ugv3bEfeJ4= -----END CERTIFICATE-----` + IntermediateWithSameSubjectAndSKID1 = `-----BEGIN CERTIFICATE----- MIIDlTCCAn2gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMx ETAPBgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwP @@ -484,6 +492,7 @@ xfBPUaspjiGALO8hBKlbVxt0RWv5MGyg2JJbSt9Ijexa6aoLzynq5gpSoEfQABUp wbfDZe4Cbio4ndASlsbtpo/5ZOuQKn9Wp54meOotFDrFntnD7XFohxMJc5YY0F1q Yk3FHd02VN0M -----END CERTIFICATE-----` + IntermediateWithSameSubjectAndSKID2 = `-----BEGIN CERTIFICATE----- MIIDlTCCAn2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCVVMx ETAPBgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwP @@ -526,6 +535,57 @@ fjlqLDHoQ1UhBmEnocFTqd7QEZtUbRWPnlJw0ZK2uFK7IYmlnBKkewPCLVGI3ihx al/8sTx3xx7fWpS+rJ3jviCpHgP+cGV/ANg8hOlyr68u0FE+x6pye00TmxcFzDuo 5/OA9jGQln82Z8inmc05wZPQPpjZxdCQteqJkNl7PrklgO5EevG9JlUArIets2Py 2Vciq5eYOIi+PlP+HI5QzlZYxSqFjJrFcfzYCJ4= +-----END CERTIFICATE-----` + + RootCertWithVid = `-----BEGIN CERTIFICATE----- +MIICdDCCAhmgAwIBAgIBATAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjExNTQzMVoYDzMwMjMwNjI5MTE1NDMxWjCBmDELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEDcguargOjH5nh4SCsflFk1ACqNBOR6Wua8huVYPBfse6 +uwfkgmyTJrCBCUAq9ayPD83jPVor1NN9YAx/V0zbsKNQME4wHQYDVR0OBBYEFM6o +kmbq4IC9K7Vo5AsHxPosNG0xMB8GA1UdIwQYMBaAFM6okmbq4IC9K7Vo5AsHxPos +NG0xMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAOdYHo1krgzyV+CT +G+RKcYoxHr6YS9ddNOJibjBx/I63AiEAxNl6kcOH0Rovwi2wySHvTD26kfUYJAmi +HGBcCo5whZU= +-----END CERTIFICATE-----` + + IntermediateCertWithVid1 = `-----BEGIN CERTIFICATE----- +MIICejCCAiGgAwIBAgIBAzAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjEyMDczMloYDzMwMjMwNjI5MTIwNzMyWjCBrjELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGC +onwCAgwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOTNh8u27CnRGdj0 +G0/z0oo9rsKcpgUogQ8fYYEg/QClYFHJuhFbf1M+VdeMScbllpt4kGH2ih7aU1b7 +1jRkVsyjQjBAMB0GA1UdDgQWBBQOjOjIuKpQvCWFVrmxnMLH2cUvFzAfBgNVHSME +GDAWgBTOqJJm6uCAvSu1aOQLB8T6LDRtMTAKBggqhkjOPQQDAgNHADBEAiAOQSIQ +sdClGJ86LQ1p7e+kb0Dg+YsyxIv2XHdUvIVn2gIgBkbzBccRbDG3p/+gnPhF+7xP +T/SKbO+GZvoizizl6Gc= +-----END CERTIFICATE-----` + + IntermediateCertWithVid2 = `-----BEGIN CERTIFICATE----- +MIICezCCAiGgAwIBAgIBBDAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjEzMDcwNVoYDzMwMjMwNjI5MTMwNzA1WjCBrjELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYyMRQwEgYKKwYBBAGC +onwCAgwERkZGMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOTNh8u27CnRGdj0 +G0/z0oo9rsKcpgUogQ8fYYEg/QClYFHJuhFbf1M+VdeMScbllpt4kGH2ih7aU1b7 +1jRkVsyjQjBAMB0GA1UdDgQWBBQOjOjIuKpQvCWFVrmxnMLH2cUvFzAfBgNVHSME +GDAWgBTOqJJm6uCAvSu1aOQLB8T6LDRtMTAKBggqhkjOPQQDAgNIADBFAiEAkApx +PWFFDoptmYnsW1QhKqrcD+xmFgJA4SWTH5Q1efMCIDWqdG0sAgum+FphfM4HF6XV +M6mDL6NurBAW1pJlg8OT -----END CERTIFICATE-----` RootIssuer = "MDQxCzAJBgNVBAYTAkFVMRMwEQYDVQQIDApzb21lLXN0YXRlMRAwDgYDVQQKDAdyb290LWNh" @@ -590,4 +650,15 @@ al/8sTx3xx7fWpS+rJ3jviCpHgP+cGV/ANg8hOlyr68u0FE+x6pye00TmxcFzDuo DataDigest = "9a5d2c1f4b3e6f8d7b1a0c9e2f5d8b7" TestCertPemVid = 4701 + + RootCertWithVidSubject = "MIGYMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjE=" + RootCertWithVidSubjectKeyID = "CE:A8:92:66:EA:E0:80:BD:2B:B5:68:E4:0B:07:C4:FA:2C:34:6D:31" + RootCertWithVidVid = 65521 + + IntermediateCertWithVidSubject = "MIGuMQswCQYDVQQGEwJVUzERMA8GA1UECAwITmV3IFlvcmsxETAPBgNVBAcMCE5ldyBZb3JrMRgwFgYDVQQKDA9FeGFtcGxlIENvbXBhbnkxGTAXBgNVBAsMEFRlc3RpbmcgRGl2aXNpb24xGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTEUMBIGCisGAQQBgqJ8AgEMBEZGRjExFDASBgorBgEEAYKifAICDARGRkYx" + IntermediateCertWithVidSubjectKeyID = "0E:8C:E8:C8:B8:AA:50:BC:25:85:56:B9:B1:9C:C2:C7:D9:C5:2F:17" + IntermediateCertWithVid1SerialNumber = "3" + IntermediateCertWithVid2SerialNumber = "4" + IntermediateCertWithVid1Vid = 65521 + IntermediateCertWithVid2Vid = 65522 ) diff --git a/integration_tests/constants/intermediate_cert_with_vid_1 b/integration_tests/constants/intermediate_cert_with_vid_1 new file mode 100644 index 000000000..41e40b049 --- /dev/null +++ b/integration_tests/constants/intermediate_cert_with_vid_1 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICejCCAiGgAwIBAgIBAzAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjEyMDczMloYDzMwMjMwNjI5MTIwNzMyWjCBrjELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMRQwEgYKKwYBBAGC +onwCAgwERkZGMTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOTNh8u27CnRGdj0 +G0/z0oo9rsKcpgUogQ8fYYEg/QClYFHJuhFbf1M+VdeMScbllpt4kGH2ih7aU1b7 +1jRkVsyjQjBAMB0GA1UdDgQWBBQOjOjIuKpQvCWFVrmxnMLH2cUvFzAfBgNVHSME +GDAWgBTOqJJm6uCAvSu1aOQLB8T6LDRtMTAKBggqhkjOPQQDAgNHADBEAiAOQSIQ +sdClGJ86LQ1p7e+kb0Dg+YsyxIv2XHdUvIVn2gIgBkbzBccRbDG3p/+gnPhF+7xP +T/SKbO+GZvoizizl6Gc= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/integration_tests/constants/intermediate_cert_with_vid_2 b/integration_tests/constants/intermediate_cert_with_vid_2 new file mode 100644 index 000000000..f3397aa54 --- /dev/null +++ b/integration_tests/constants/intermediate_cert_with_vid_2 @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICezCCAiGgAwIBAgIBBDAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjEzMDcwNVoYDzMwMjMwNjI5MTMwNzA1WjCBrjELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYyMRQwEgYKKwYBBAGC +onwCAgwERkZGMjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOTNh8u27CnRGdj0 +G0/z0oo9rsKcpgUogQ8fYYEg/QClYFHJuhFbf1M+VdeMScbllpt4kGH2ih7aU1b7 +1jRkVsyjQjBAMB0GA1UdDgQWBBQOjOjIuKpQvCWFVrmxnMLH2cUvFzAfBgNVHSME +GDAWgBTOqJJm6uCAvSu1aOQLB8T6LDRtMTAKBggqhkjOPQQDAgNIADBFAiEAkApx +PWFFDoptmYnsW1QhKqrcD+xmFgJA4SWTH5Q1efMCIDWqdG0sAgum+FphfM4HF6XV +M6mDL6NurBAW1pJlg8OT +-----END CERTIFICATE----- \ No newline at end of file diff --git a/integration_tests/constants/root_cert_with_vid b/integration_tests/constants/root_cert_with_vid new file mode 100644 index 000000000..730ce43ce --- /dev/null +++ b/integration_tests/constants/root_cert_with_vid @@ -0,0 +1,16 @@ +-----BEGIN CERTIFICATE----- +MIICdDCCAhmgAwIBAgIBATAKBggqhkjOPQQDAjCBmDELMAkGA1UEBhMCVVMxETAP +BgNVBAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhh +bXBsZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQD +DA93d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMCAXDTI0MDIy +NjExNTQzMVoYDzMwMjMwNjI5MTE1NDMxWjCBmDELMAkGA1UEBhMCVVMxETAPBgNV +BAgMCE5ldyBZb3JrMREwDwYDVQQHDAhOZXcgWW9yazEYMBYGA1UECgwPRXhhbXBs +ZSBDb21wYW55MRkwFwYDVQQLDBBUZXN0aW5nIERpdmlzaW9uMRgwFgYDVQQDDA93 +d3cuZXhhbXBsZS5jb20xFDASBgorBgEEAYKifAIBDARGRkYxMFkwEwYHKoZIzj0C +AQYIKoZIzj0DAQcDQgAEDcguargOjH5nh4SCsflFk1ACqNBOR6Wua8huVYPBfse6 +uwfkgmyTJrCBCUAq9ayPD83jPVor1NN9YAx/V0zbsKNQME4wHQYDVR0OBBYEFM6o +kmbq4IC9K7Vo5AsHxPosNG0xMB8GA1UdIwQYMBaAFM6okmbq4IC9K7Vo5AsHxPos +NG0xMAwGA1UdEwQFMAMBAf8wCgYIKoZIzj0EAwIDSQAwRgIhAOdYHo1krgzyV+CT +G+RKcYoxHr6YS9ddNOJibjBx/I63AiEAxNl6kcOH0Rovwi2wySHvTD26kfUYJAmi +HGBcCo5whZU= +-----END CERTIFICATE----- \ No newline at end of file diff --git a/integration_tests/grpc_rest/pki/helpers.go b/integration_tests/grpc_rest/pki/helpers.go index 4873fbee8..744c0bb99 100644 --- a/integration_tests/grpc_rest/pki/helpers.go +++ b/integration_tests/grpc_rest/pki/helpers.go @@ -1983,4 +1983,130 @@ func Demo(suite *utils.TestSuite) { suite.AssertNotFound(err) _, err = GetX509Cert(suite, testconstants.LeafCertWithSameSubjectAndSKIDSubject, testconstants.LeafCertWithSameSubjectAndSKIDSubjectKeyID) suite.AssertNotFound(err) + + // Add VID scoped X509 certificate + + // Check that if root cert is VID scoped and RootVID==CertVID==AccountVID then adding x509 should succeed + // Add root certificate + msgProposeAddX509RootCert = pkitypes.MsgProposeAddX509RootCert{ + Cert: testconstants.RootCertWithVid, + Vid: testconstants.RootCertWithVidVid, + Signer: aliceAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgProposeAddX509RootCert}, aliceName, aliceAccount) + require.NoError(suite.T, err) + + msgApproveAddX509RootCert = pkitypes.MsgApproveAddX509RootCert{ + Subject: testconstants.RootCertWithVidSubject, + SubjectKeyId: testconstants.RootCertWithVidSubjectKeyID, + Signer: jackAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgApproveAddX509RootCert}, jackName, jackAccount) + require.NoError(suite.T, err) + + // Register new Vendor account + vendorName = utils.RandString() + vendorAccount = test_dclauth.CreateVendorAccount( + suite, + vendorName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + testconstants.RootCertWithVidVid, + testconstants.ProductIDsEmpty, + aliceName, + aliceAccount, + jackName, + jackAccount, + testconstants.Info, + ) + require.NotNil(suite.T, vendorAccount) + + // Add an intermediate certificate + msgAddX509Cert = pkitypes.MsgAddX509Cert{ + Cert: testconstants.IntermediateCertWithVid1, + Signer: vendorAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) + require.NoError(suite.T, err) + + // Check approved certificates + certs, _ = GetX509Cert(suite, testconstants.RootCertWithVidSubject, testconstants.RootCertWithVidSubjectKeyID) + require.Equal(suite.T, 1, len(certs.Certs)) + certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVidSubject, testconstants.IntermediateCertWithVidSubjectKeyID) + require.Equal(suite.T, 1, len(certs.Certs)) + + // Check that if root cert is VID scoped and rootVID != CertVID then adding an intermediate cert should fail + // Add an intermediate certificate + msgAddX509Cert = pkitypes.MsgAddX509Cert{ + Cert: testconstants.IntermediateCertWithVid2, + Signer: vendorAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, vendorName, vendorAccount) + require.Error(suite.T, err) + + // Check there is only one approved intermediate certificate + certs, _ = GetX509Cert(suite, testconstants.IntermediateCertWithVidSubject, testconstants.IntermediateCertWithVidSubjectKeyID) + require.Equal(suite.T, 1, len(certs.Certs)) + require.Equal(suite.T, testconstants.IntermediateCertWithVid1SerialNumber, certs.Certs[0].SerialNumber) + + // Check that if root cert is non-VID scoped and CertVID != AccountVID then adding an intermediate cert should fail + // Ensure that there is a non-VID root cert exists + certs, _ = GetX509Cert(suite, testconstants.PAACertNoVidSubject, testconstants.PAACertNoVidSubjectKeyID) + require.Equal(suite.T, 1, len(certs.Certs)) + + // Try to submit txn with another Vendor + newVendorName := utils.RandString() + newVendorAccount := test_dclauth.CreateVendorAccount( + suite, + newVendorName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + 1234, + testconstants.ProductIDsEmpty, + aliceName, + aliceAccount, + jackName, + jackAccount, + testconstants.Info, + ) + require.NotNil(suite.T, newVendorAccount) + + // Add an intermediate certificate + msgAddX509Cert = pkitypes.MsgAddX509Cert{ + Cert: testconstants.PAICertWithNumericVid, + Signer: newVendorAccount.Address, + } + + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, newVendorName, newVendorAccount) + require.Error(suite.T, err) + + // Check there is no an intermediate certificate + certs, _ = GetX509Cert(suite, testconstants.PAICertWithNumericVidSubject, testconstants.PAICertWithNumericVidSubjectKeyID) + require.Equal(suite.T, 0, len(certs.Certs)) + + // Check that if root cert is non-VID scoped and CertVID==AccountVID then adding x509 should succeed + // Create vendor with valid VID + newVendorName = utils.RandString() + newVendorAccount = test_dclauth.CreateVendorAccount( + suite, + newVendorName, + dclauthtypes.AccountRoles{dclauthtypes.Vendor}, + testconstants.IntermediateCertWithVid2Vid, + testconstants.ProductIDsEmpty, + aliceName, + aliceAccount, + jackName, + jackAccount, + testconstants.Info, + ) + require.NotNil(suite.T, newVendorAccount) + + // Add an intermediate certificate + msgAddX509Cert = pkitypes.MsgAddX509Cert{ + Cert: testconstants.PAICertWithNumericVid, + Signer: newVendorAccount.Address, + } + _, err = suite.BuildAndBroadcastTx([]sdk.Msg{&msgAddX509Cert}, newVendorName, newVendorAccount) + require.NoError(suite.T, err) + // Check there is only one approved intermediate certificate + certs, _ = GetX509Cert(suite, testconstants.PAICertWithNumericVidSubject, testconstants.PAICertWithNumericVidSubjectKeyID) + require.Equal(suite.T, 1, len(certs.Certs)) } diff --git a/types/pki/errors.go b/types/pki/errors.go index f0ae5052b..2530182b0 100644 --- a/types/pki/errors.go +++ b/types/pki/errors.go @@ -48,6 +48,7 @@ var ( ErrMessageVidNotEqualRootCertVid = sdkerrors.Register(ModuleName, 437, "Message vid is not equal to ledger's root certificate vid") ErrCertNotChainedBack = sdkerrors.Register(ModuleName, 438, "Certificate is not chained back to a root certificate on DCL") ErrCertVidNotEqualAccountVid = sdkerrors.Register(ModuleName, 439, "account's vid is not equal to ledger's certificate vid") + ErrCertVidNotEqualToRootVid = sdkerrors.Register(ModuleName, 440, "certificate's vid is not equal to vid of root certificate ") ) func NewErrUnauthorizedRole(transactionName string, requiredRole types.AccountRole) error { @@ -206,6 +207,28 @@ func NewErrExistingCertVidNotEqualAccountVid(subject string, subjectKeyID string subject, subjectKeyID, vid) } +func NewErrRootCertVidNotEqualToAccountVidOrCertVid(rootVID int32, accountVID int32, certVID int32) error { + if rootVID != certVID { + return sdkerrors.Wrapf(ErrCertVidNotEqualToRootVid, + "Root certificate is VID scoped: An intermediate certificate must be also VID scoped to the same VID as a root one: "+ + "Root certificate's VID = %v, Certificate's VID = %v", + rootVID, certVID) + } + + return sdkerrors.Wrapf(ErrCertVidNotEqualAccountVid, + "Root certificate is VID scoped: "+ + "Only a Vendor associated with this VID can add an intermediate certificate: "+ + "Root certificate's VID = %v, Account VID = %v", + rootVID, accountVID) +} + +func NewErrAccountVidNotEqualToCertVid(accountVID int32, certVID int32) error { + return sdkerrors.Wrapf(ErrCertVidNotEqualAccountVid, + "Intermediate certificate is VID scoped: Only a Vendor associated with this VID can add an intermediate certificate: "+ + "Account VID = %v, Certificate's VID = %v", + accountVID, certVID) +} + func NewErrCRLSignerCertificatePidNotEqualMsgPid(certificatePid int32, messagePid int32) error { return sdkerrors.Wrapf( ErrCRLSignerCertificatePidNotEqualMsgPid, diff --git a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.pki/module/types/pki/tx.ts b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.pki/module/types/pki/tx.ts index a6ad733ec..3eb776561 100644 --- a/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.pki/module/types/pki/tx.ts +++ b/vue/src/store/generated/zigbee-alliance/distributed-compliance-ledger/zigbeealliance.distributedcomplianceledger.pki/module/types/pki/tx.ts @@ -2427,6 +2427,7 @@ export interface Msg { AssignVid(request: MsgAssignVid): Promise AddNocX509RootCert(request: MsgAddNocX509RootCert): Promise /** this line is used by starport scaffolding # proto/tx/rpc */ + /** this line is used by starport scaffolding # proto/tx/rpc */ RemoveX509Cert(request: MsgRemoveX509Cert): Promise } diff --git a/x/pki/handler_test.go b/x/pki/handler_test.go index 8780db134..e091030a3 100644 --- a/x/pki/handler_test.go +++ b/x/pki/handler_test.go @@ -787,6 +787,126 @@ func TestHandler_AddX509Cert(t *testing.T) { } } +func TestHandler_AddX509Cert_RootVID_Equal_To_CertVID_And_AccountVID(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := createPAACertWithNumericVidOptions() + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.PAACertWithNumericVidVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericPidVid) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certs, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(certs)) + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.PAICertWithNumericPidVidSubject, testconstants.PAICertWithNumericPidVidSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.PAICertWithNumericPidVidSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.PAICertWithNumericPidVidSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) +} + +func TestHandler_AddX509Cert_Non_VID_Scoped_Root__ChildVID_Equal_To_AccountVID(t *testing.T) { + setup := Setup(t) + // store root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.PAACertNoVid, + info: testconstants.Info, + subject: testconstants.PAACertNoVidSubject, + subjectKeyID: testconstants.PAACertNoVidSubjectKeyID, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 65522) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericVid) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.NoError(t, err) + + // query certificate + certs, _ := queryAllApprovedCertificates(setup) + require.Equal(t, 2, len(certs)) + intermediateCerts, _ := queryApprovedCertificates(setup, testconstants.PAICertWithNumericVidSubject, testconstants.PAICertWithNumericVidSubjectKeyID) + require.Equal(t, 1, len(intermediateCerts.Certs)) + require.Equal(t, testconstants.PAICertWithNumericVidSubject, intermediateCerts.Certs[0].Subject) + require.Equal(t, testconstants.PAICertWithNumericVidSubjectKeyID, intermediateCerts.Certs[0].SubjectKeyId) +} + +func TestHandler_AddX509Cert_Root_VID_Does_Not_Equal_To_ChildVID(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertWithVid, + info: testconstants.Info, + subject: testconstants.RootCertWithVidSubject, + subjectKeyID: testconstants.RootCertWithVidSubjectKeyID, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, testconstants.RootCertWithVidVid) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertWithVid2) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertVidNotEqualToRootVid.Is(err)) +} + +func TestHandler_AddX509Cert_Root_VID_Does_Not_Equal_To_AccountVID(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.RootCertWithVid, + info: testconstants.Info, + subject: testconstants.RootCertWithVidSubject, + subjectKeyID: testconstants.RootCertWithVidSubjectKeyID, + vid: testconstants.RootCertWithVidVid, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1111) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.IntermediateCertWithVid1) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertVidNotEqualAccountVid.Is(err)) +} + +func TestHandler_AddX509Cert_Non_Root_VID__Child_VID_Does_Not_Equal_To_AccountVID(t *testing.T) { + setup := Setup(t) + + // store root certificate + rootCertOptions := &rootCertOptions{ + pemCert: testconstants.PAACertNoVid, + info: testconstants.Info, + subject: testconstants.PAACertNoVidSubject, + subjectKeyID: testconstants.PAACertNoVidSubjectKeyID, + } + proposeAndApproveRootCertificate(setup, setup.Trustee1, rootCertOptions) + + accAddress := GenerateAccAddress() + setup.AddAccount(accAddress, []dclauthtypes.AccountRole{dclauthtypes.Vendor}, 1111) + + // add x509 certificate + addX509Cert := types.NewMsgAddX509Cert(accAddress.String(), testconstants.PAICertWithNumericVid) + _, err := setup.Handler(setup.Ctx, addX509Cert) + require.Error(t, err) + require.True(t, pkitypes.ErrCertVidNotEqualAccountVid.Is(err)) +} + func TestHandler_AddX509Cert_ForInvalidCertificate(t *testing.T) { setup := Setup(t) diff --git a/x/pki/keeper/approved_certificates.go b/x/pki/keeper/approved_certificates.go index 8e7c53acc..0b6c7a869 100644 --- a/x/pki/keeper/approved_certificates.go +++ b/x/pki/keeper/approved_certificates.go @@ -134,17 +134,17 @@ func (k Keeper) IsApprovedCertificatePresent( // Returns the RootSubject/RootSubjectKeyID combination or an error in case no valid certificate chain can be built. func (k Keeper) verifyCertificate(ctx sdk.Context, x509Certificate *x509.Certificate, -) (string, string, error) { +) (*x509.Certificate, error) { //nolint:nestif if x509Certificate.IsSelfSigned() { // in this system a certificate is self-signed if and only if it is a root certificate if err := x509Certificate.Verify(x509Certificate, ctx.BlockTime()); err == nil { - return x509Certificate.Subject, x509Certificate.SubjectKeyID, nil + return x509Certificate, nil } } else { parentCertificates, found := k.GetApprovedCertificates(ctx, x509Certificate.Issuer, x509Certificate.AuthorityKeyID) if !found { - return "", "", pkitypes.NewErrInvalidCertificate( + return nil, pkitypes.NewErrInvalidCertificate( fmt.Sprintf("Certificate verification failed for certificate with subject=%v and subjectKeyID=%v", x509Certificate.Subject, x509Certificate.SubjectKeyID)) } @@ -161,13 +161,13 @@ func (k Keeper) verifyCertificate(ctx sdk.Context, } // verify parent certificate - if subject, subjectKeyID, err := k.verifyCertificate(ctx, parentX509Certificate); err == nil { - return subject, subjectKeyID, nil + if rootCertificate, err := k.verifyCertificate(ctx, parentX509Certificate); err == nil { + return rootCertificate, nil } } } - return "", "", pkitypes.NewErrInvalidCertificate( + return nil, pkitypes.NewErrInvalidCertificate( fmt.Sprintf("Certificate verification failed for certificate with subject=%v and subjectKeyID=%v", x509Certificate.Subject, x509Certificate.SubjectKeyID)) } diff --git a/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go b/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go index dc8da51aa..33f6a7fd8 100644 --- a/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go +++ b/x/pki/keeper/msg_server_add_noc_x_509_root_cert.go @@ -40,7 +40,7 @@ func (k msgServer) AddNocX509RootCert(goCtx context.Context, msg *types.MsgAddNo } // verify certificate - _, _, err = k.verifyCertificate(ctx, x509Certificate) + _, err = k.verifyCertificate(ctx, x509Certificate) if err != nil { return nil, err } diff --git a/x/pki/keeper/msg_server_add_pki_revocation_distribution_point.go b/x/pki/keeper/msg_server_add_pki_revocation_distribution_point.go index e8b93a245..52d7c365f 100644 --- a/x/pki/keeper/msg_server_add_pki_revocation_distribution_point.go +++ b/x/pki/keeper/msg_server_add_pki_revocation_distribution_point.go @@ -117,7 +117,7 @@ func (k msgServer) checkRootCert(ctx sdk.Context, crlSignerCertificate *x509.Cer func (k msgServer) checkNonRootCert(ctx sdk.Context, crlSignerCertificate *x509.Certificate) error { // check that it's chained back to a cert on DCL - if _, _, err := k.verifyCertificate(ctx, crlSignerCertificate); err != nil { + if _, err := k.verifyCertificate(ctx, crlSignerCertificate); err != nil { return pkitypes.NewErrCertNotChainedBack() } diff --git a/x/pki/keeper/msg_server_add_x_509_cert.go b/x/pki/keeper/msg_server_add_x_509_cert.go index 873fb342f..962095f39 100644 --- a/x/pki/keeper/msg_server_add_x_509_cert.go +++ b/x/pki/keeper/msg_server_add_x_509_cert.go @@ -4,10 +4,10 @@ import ( "context" sdk "github.com/cosmos/cosmos-sdk/types" - "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" - "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/x509" pkitypes "github.com/zigbee-alliance/distributed-compliance-ledger/types/pki" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/types" + "github.com/zigbee-alliance/distributed-compliance-ledger/x/pki/x509" ) func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) (*types.MsgAddX509CertResponse, error) { @@ -57,10 +57,39 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) } // Valid certificate chain must be built for new certificate - rootCertificateSubject, rootCertificateSubjectKeyID, err := k.verifyCertificate(ctx, x509Certificate) + rootCert, err := k.verifyCertificate(ctx, x509Certificate) if err != nil { return nil, err } + // Check Root and Intermediate certs for VID scoping + rootVid, err := x509.GetVidFromSubject(x509.ToSubjectAsText(rootCert.SubjectAsText)) + if err != nil { + return nil, pkitypes.NewErrInvalidVidFormat(err) + } + childVid, err := x509.GetVidFromSubject(x509Certificate.SubjectAsText) + if err != nil { + return nil, pkitypes.NewErrInvalidVidFormat(err) + } + signerAddr, err := sdk.AccAddressFromBech32(msg.Signer) + if err != nil { + return nil, pkitypes.NewErrInvalidAddress(err) + } + + signerAccount, _ := k.dclauthKeeper.GetAccountO(ctx, signerAddr) + accountVID := signerAccount.VendorID + + if rootVid != 0 { + // If added under a VID scoped root CA: Intermediate cert must be also VID scoped to the same VID as a root one. + // Only a Vendor associated with this VID can add an intermediate certificate. So `rootVid == childVid == accountVID` + // condition must hold + if rootVid != childVid || rootVid != accountVID { + return nil, pkitypes.NewErrRootCertVidNotEqualToAccountVidOrCertVid(rootVid, accountVID, childVid) + } + // If added under a non-VID scoped root CA associated with a VID: Intermediate cert must be either VID scoped to the same VID, or non-VID scoped. + // Only a Vendor associated with this VID can add an intermediate certificate. + } else if childVid != 0 && childVid != accountVID { + return nil, pkitypes.NewErrAccountVidNotEqualToCertVid(accountVID, childVid) + } // create new certificate certificate := types.NewNonRootCertificate( @@ -71,8 +100,8 @@ func (k msgServer) AddX509Cert(goCtx context.Context, msg *types.MsgAddX509Cert) x509Certificate.SerialNumber, x509Certificate.Issuer, x509Certificate.AuthorityKeyID, - rootCertificateSubject, - rootCertificateSubjectKeyID, + rootCert.Subject, + rootCert.SubjectKeyID, msg.Signer, ) diff --git a/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go b/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go index c9a6038a3..1ef8ff0cf 100644 --- a/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go +++ b/x/pki/keeper/msg_server_propose_add_x_509_root_cert.go @@ -50,7 +50,7 @@ func (k msgServer) ProposeAddX509RootCert(goCtx context.Context, msg *types.MsgP } // verify certificate - _, _, err = k.verifyCertificate(ctx, x509Certificate) + _, err = k.verifyCertificate(ctx, x509Certificate) if err != nil { return nil, err } diff --git a/x/pki/keeper/msg_server_update_pki_revocation_distribution_point.go b/x/pki/keeper/msg_server_update_pki_revocation_distribution_point.go index 20c60492c..eb3bdcc1e 100644 --- a/x/pki/keeper/msg_server_update_pki_revocation_distribution_point.go +++ b/x/pki/keeper/msg_server_update_pki_revocation_distribution_point.go @@ -186,7 +186,7 @@ func (k msgServer) verifyUpdatedPAI(ctx sdk.Context, newCertificatePem string, r } // check that it's chained back to a cert on DCL - if _, _, err := k.verifyCertificate(ctx, newCertificate); err != nil { + if _, err = k.verifyCertificate(ctx, newCertificate); err != nil { return pkitypes.NewErrCertNotChainedBack() }