diff --git a/verify.go b/verify.go index f09e272..d4a8832 100644 --- a/verify.go +++ b/verify.go @@ -210,8 +210,13 @@ func parseSignedData(data []byte) (*PKCS7, error) { // Compound octet string if compound.IsCompound { if compound.Tag == 4 { - if _, err = asn1.Unmarshal(compound.Bytes, &content); err != nil { - return nil, err + for len(compound.Bytes) > 0 { + var cdata asn1.RawValue + if _, err = asn1.Unmarshal(compound.Bytes, &cdata); err != nil { + return nil, err + } + content = append(content, cdata.Bytes...) + compound.Bytes = compound.Bytes[len(cdata.FullBytes):] } } else { content = compound.Bytes diff --git a/verify_test.go b/verify_test.go index cd7d32e..2d564a2 100644 --- a/verify_test.go +++ b/verify_test.go @@ -6,6 +6,7 @@ import ( "crypto/rsa" "crypto/x509" "encoding/base64" + "encoding/hex" "encoding/pem" "io/ioutil" "os" @@ -595,3 +596,120 @@ but that's not what ships are built for. } os.Remove(tmpContentFile.Name()) // clean up } + +var sampleAppleAppAttestationReceiptFixture = []byte(` +-----BEGIN ----- +MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0B +BwGggCSABIID6DGCBAswIwIBAgIBAQQbOFlFMjNOWlM1Ny5jb20ua2F5YWsudHJh +dmVsMIIC7gIBAwIBAQSCAuQwggLgMIICZqADAgECAgYBdNZm2hAwCgYIKoZIzj0E +AwIwTzEjMCEGA1UEAwwaQXBwbGUgQXBwIEF0dGVzdGF0aW9uIENBIDExEzARBgNV +BAoMCkFwcGxlIEluYy4xEzARBgNVBAgMCkNhbGlmb3JuaWEwHhcNMjAwOTI3MjAy +ODE4WhcNMjAwOTMwMjAyODE4WjCBkTFJMEcGA1UEAwxANTY3N2VhOGQyYTc0YWQ2 +Y2IyYThkODZiN2UxZmJkZmM4ODRiMjJmNWVlNjEzM2MwOTg5MTE1NDMwOTc4NzY0 +YTEaMBgGA1UECwwRQUFBIENlcnRpZmljYXRpb24xEzARBgNVBAoMCkFwcGxlIElu +Yy4xEzARBgNVBAgMCkNhbGlmb3JuaWEwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNC +AASVMXfBQ2n1hERgyf113lWGstIXHIbeiLJi+oIYyZj/aqNGPACJWSmRK/v5B67u +Z2bZrNNSoRrwJyoNiwerRvmdo4HqMIHnMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/ +BAQDAgTwMHUGCSqGSIb3Y2QIBQRoMGakAwIBCr+JMAMCAQG/iTEDAgEAv4kyAwIB +Ab+JMwMCAQG/iTQdBBs4WUUyM05aUzU3LmNvbS5rYXlhay50cmF2ZWylBgQEc2tz +IL+JNgMCAQW/iTcDAgEAv4k5AwIBAL+JOgMCAQAwGwYJKoZIhvdjZAgHBA4wDL+K +eAgEBjE0LjAuMTAzBgkqhkiG92NkCAIEJjAkoSIEIMmvmBS106CCCA0l+C2IhciY +KtSnKp+1qGmv597EqyV9MAoGCCqGSM49BAMCA2gAMGUCMQC2xV2A+e9j96iphB6G +3Vm53fzMw+lZ/LlgKAHvZy6K3gNCnyMev8/O79TwiHFxBqcCMDwneBrN7P2REtFV +dPjdGFSqJQ1AS2VJtX31VRHZzY7FNRLqyTPqkuF9xnay6NWlYzAoAgEEAgEBBCC9 +2s44kCAWK/w87A2CBCqO7rxzyw/c+bUL3gOkdjKdZjBgAgEFAgEBBFgrZVk0U1Nu +T2pkaWsrWGkzaUJTK1NrR1ZTR004NmlKeVBTYWMrbnUxdU94d2ZvVEFLbXg4U2N0 +M1hyQmorenYvcE9kVUpodzJ6N3E2SDhHem8vekJtdz09MA4CAQYCAQEEBkFUVEVT +VDASAgEHAgEBBApwcm9kdWN0aW9uMCACAQwCAQEEGDIwMjAtMDktMjhUMjA6Mjg6 +MTkEJy45NDJaMCACARUCAQEEGDIwMjAtMTItMjdUMjA6Mjg6MTkuOTQyWgAAAAAA +AKCAMIIDrTCCA1SgAwIBAgIQWTNWreVZgs9EQjes30UbUzAKBggqhkjOPQQDAjB8 +MTAwLgYDVQQDDCdBcHBsZSBBcHBsaWNhdGlvbiBJbnRlZ3JhdGlvbiBDQSA1IC0g +RzExJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYD +VQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yMDA1MTkxNzQ3MzFaFw0y +MTA2MTgxNzQ3MzFaMFoxNjA0BgNVBAMMLUFwcGxpY2F0aW9uIEF0dGVzdGF0aW9u +IEZyYXVkIFJlY2VpcHQgU2lnbmluZzETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkG +A1UEBhMCVVMwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAR/6RU0bMOKe5g8k9HQ +Q1/Yq9pWcATTLFiGZVGVerR498sq+LpF9/p46sYsSeT5zcCEtQMU8QIz2pt2+kQq +K7hyo4IB2DCCAdQwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBTZF/5LZ5A4S5L0 +287VV4AUC489yTBDBggrBgEFBQcBAQQ3MDUwMwYIKwYBBQUHMAGGJ2h0dHA6Ly9v +Y3NwLmFwcGxlLmNvbS9vY3NwMDMtYWFpY2E1ZzEwMTCCARwGA1UdIASCARMwggEP +MIIBCwYJKoZIhvdjZAUBMIH9MIHDBggrBgEFBQcCAjCBtgyBs1JlbGlhbmNlIG9u +IHRoaXMgY2VydGlmaWNhdGUgYnkgYW55IHBhcnR5IGFzc3VtZXMgYWNjZXB0YW5j +ZSBvZiB0aGUgdGhlbiBhcHBsaWNhYmxlIHN0YW5kYXJkIHRlcm1zIGFuZCBjb25k +aXRpb25zIG9mIHVzZSwgY2VydGlmaWNhdGUgcG9saWN5IGFuZCBjZXJ0aWZpY2F0 +aW9uIHByYWN0aWNlIHN0YXRlbWVudHMuMDUGCCsGAQUFBwIBFilodHRwOi8vd3d3 +LmFwcGxlLmNvbS9jZXJ0aWZpY2F0ZWF1dGhvcml0eTAdBgNVHQ4EFgQUaR7HD0fs +443ddTdE8+nhWmwQViUwDgYDVR0PAQH/BAQDAgeAMA8GCSqGSIb3Y2QMDwQCBQAw +CgYIKoZIzj0EAwIDRwAwRAIgJRgWXF4pnFn2hTmtXduZ9jc+9g7NCEWp/Xca1iQt +LCICIF0qmypfq6NjgWWNGED3r0gL12uhlNg0IIf01pNbtRuuMIIC+TCCAn+gAwIB +AgIQVvuD1Cv/jcM3mSO1Wq5uvTAKBggqhkjOPQQDAzBnMRswGQYDVQQDDBJBcHBs +ZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0 +aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0xOTAz +MjIxNzUzMzNaFw0zNDAzMjIwMDAwMDBaMHwxMDAuBgNVBAMMJ0FwcGxlIEFwcGxp +Y2F0aW9uIEludGVncmF0aW9uIENBIDUgLSBHMTEmMCQGA1UECwwdQXBwbGUgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNV +BAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEks5jvX2GsasoCjsc4a/7 +BJSAkaz2Md+myyg1b0RL4SHlV90SjY26gnyVvkn6vjPKrs0EGfEvQyX69L6zy4N+ +uqOB9zCB9DAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFLuw3qFYM4iapIqZ +3r6966/ayySrMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcwAYYqaHR0cDovL29j +c3AuYXBwbGUuY29tL29jc3AwMy1hcHBsZXJvb3RjYWczMDcGA1UdHwQwMC4wLKAq +oCiGJmh0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlcm9vdGNhZzMuY3JsMB0GA1Ud +DgQWBBTZF/5LZ5A4S5L0287VV4AUC489yTAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZI +hvdjZAYCAwQCBQAwCgYIKoZIzj0EAwMDaAAwZQIxAI1vpp+h4OTsW05zipJ/PXhT +mI/02h9YHsN1Sv44qEwqgxoaqg2mZG3huZPo0VVM7QIwZzsstOHoNwd3y9Xsdqga +OlU7PzVqyMXmkrDhYb6ASWnkXyupbOERAqrMYdk4t3NKMIICQzCCAcmgAwIBAgII +LcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwSQXBwbGUgUm9vdCBDQSAt +IEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEG +A1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcNMTQwNDMwMTgxOTA2WhcN +MzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAk +BgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApB +cHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49AgEGBSuBBAAiA2IABJjp +Lz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtfTjjTuxxEtX/1H7YyYl3J +6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517IDvYuVTZXpmkOlEKMaNC +MEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySrMA8GA1UdEwEB/wQFMAMB +Af8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMQCD6cHEFl4aXTQY +2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4at+qIxUCMG1mihDK1A3U +T82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM6BgD56KyKAAAMYIBljCC +AZICAQEwgZAwfDEwMC4GA1UEAwwnQXBwbGUgQXBwbGljYXRpb24gSW50ZWdyYXRp +b24gQ0EgNSAtIEcxMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhv +cml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMCEFkzVq3lWYLP +REI3rN9FG1MwDQYJYIZIAWUDBAIBBQCggZUwGAYJKoZIhvcNAQkDMQsGCSqGSIb3 +DQEHATAcBgkqhkiG9w0BCQUxDxcNMjAwOTI4MjAyODIwWjAqBgkqhkiG9w0BCTQx +HTAbMA0GCWCGSAFlAwQCAQUAoQoGCCqGSM49BAMCMC8GCSqGSIb3DQEJBDEiBCDL +FFlod6+72Z/XBkt+1Gg9wc1binQgsCMpZ5A1Ge4fnjAKBggqhkjOPQQDAgRHMEUC +IQCE46Koolc/FuL29/MUK1Auqt2XUJPK2DD9aDJgbPPKBwIgbsggotsin/9j1y/Z +4pBdpYCE6+FY7zCTIp/IaUWymtYAAAAAAAA= +-----END -----`) +func TestParseSignedOctetStringWithAppleAttestation(t *testing.T) { + decodedReceipt, _ := pem.Decode(sampleAppleAppAttestationReceiptFixture) + p7, err := Parse(decodedReceipt.Bytes) + if err != nil { + t.Fatal("could not parse receipt containing compound octet string", err) + } + expectedContent := "3182040b3023020102020101041b38594532334e5a5335372e636f6d2e6b617961" + + "6b2e74726176656c308202ee020103020101048202e4308202e030820266a00302010202060174d666da10" + + "300a06082a8648ce3d040302304f3123302106035504030c1a4170706c6520417070204174746573746174" + + "696f6e204341203131133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a43616c" + + "69666f726e6961301e170d3230303932373230323831385a170d3230303933303230323831385a3081913149" + + "304706035504030c4035363737656138643261373461643663623261386438366237653166626466633838346" + + "232326635656536313333633039383931313534333039373837363461311a3018060355040b0c1141414120436" + + "57274696669636174696f6e31133011060355040a0c0a4170706c6520496e632e3113301106035504080c0a436" + + "16c69666f726e69613059301306072a8648ce3d020106082a8648ce3d03010703420004953177c14369f5844460" + + "c9fd75de5586b2d2171c86de88b262fa8218c998ff6aa3463c00895929912bfbf907aeee6766d9acd352a11af02" + + "72a0d8b07ab46f99da381ea3081e7300c0603551d130101ff04023000300e0603551d0f0101ff0404030204f0307" + + "506092a864886f76364080504683066a40302010abf893003020101bf893103020100bf893203020101bf8933030" + + "20101bf89341d041b38594532334e5a5335372e636f6d2e6b6179616b2e74726176656ca5060404736b7320bf893603" + + "020105bf893703020100bf893903020100bf893a03020100301b06092a864886f763640807040e300cbf8a780804063" + + "1342e302e31303306092a864886f76364080204263024a1220420c9af9814b5d3a082080d25f82d8885c8982ad4a72a9fb5a8" + + "69afe7dec4ab257d300a06082a8648ce3d0403020368003065023100b6c55d80f9ef63f7a8a9841e86dd59b9ddfcccc3e959f" + + "cb9602801ef672e8ade03429f231ebfcfceefd4f088717106a702303c27781acdecfd9112d15574f8dd1854aa250d404b6549b5" + + "7df55511d9cd8ec53512eac933ea92e17dc676b2e8d5a56330280201040201010420bddace389020162bfc3cec0d82042a8eee" + + "bc73cb0fdcf9b50bde03a476329d66306002010502010104582b65593453536e4f6a64696b2b5869336942532b536b47565347" + + "4d3836694a79505361632b6e7531754f7877666f54414b6d7838536374335872426a2b7a762f704f64554a6877327a37713648" + + "38477a6f2f7a426d773d3d300e02010602010104064154544553543012020107020101040a70726f64756374696f6e30200201" + + "0c0201010418323032302d30392d32385432303a32383a31392e3934325a30200201150201010418323032302d31322d3237" + + "5432303a32383a31392e3934325a" + if hex.EncodeToString(p7.Content) != expectedContent { + t.Fatal("could not parse contained compound octet string content fully") + } +}