diff options
| author | David Howells <dhowells@redhat.com> | 2016-03-03 16:49:27 -0500 |
|---|---|---|
| committer | David Howells <dhowells@redhat.com> | 2016-03-03 16:49:27 -0500 |
| commit | 4e8ae72a75aae285ec5b93518b9680da198afd0d (patch) | |
| tree | f15537d13bcec9140d092fb950d4c04d3f347c2e /crypto | |
| parent | d43de6c780a84def056afaf4fb3e66bdaa1efc00 (diff) | |
X.509: Make algo identifiers text instead of enum
Make the identifier public key and digest algorithm fields text instead of
enum.
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Diffstat (limited to 'crypto')
| -rw-r--r-- | crypto/asymmetric_keys/mscode_parser.c | 14 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/pkcs7_parser.c | 18 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/pkcs7_verify.c | 8 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/public_key.c | 24 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/verify_pefile.c | 4 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/verify_pefile.h | 2 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/x509_cert_parser.c | 26 | ||||
| -rw-r--r-- | crypto/asymmetric_keys/x509_public_key.c | 17 |
8 files changed, 46 insertions, 67 deletions
diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c index adcef59eec0b..3242cbfaeaa2 100644 --- a/crypto/asymmetric_keys/mscode_parser.c +++ b/crypto/asymmetric_keys/mscode_parser.c | |||
| @@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen, | |||
| 86 | oid = look_up_OID(value, vlen); | 86 | oid = look_up_OID(value, vlen); |
| 87 | switch (oid) { | 87 | switch (oid) { |
| 88 | case OID_md4: | 88 | case OID_md4: |
| 89 | ctx->digest_algo = HASH_ALGO_MD4; | 89 | ctx->digest_algo = "md4"; |
| 90 | break; | 90 | break; |
| 91 | case OID_md5: | 91 | case OID_md5: |
| 92 | ctx->digest_algo = HASH_ALGO_MD5; | 92 | ctx->digest_algo = "md5"; |
| 93 | break; | 93 | break; |
| 94 | case OID_sha1: | 94 | case OID_sha1: |
| 95 | ctx->digest_algo = HASH_ALGO_SHA1; | 95 | ctx->digest_algo = "sha1"; |
| 96 | break; | 96 | break; |
| 97 | case OID_sha256: | 97 | case OID_sha256: |
| 98 | ctx->digest_algo = HASH_ALGO_SHA256; | 98 | ctx->digest_algo = "sha256"; |
| 99 | break; | 99 | break; |
| 100 | case OID_sha384: | 100 | case OID_sha384: |
| 101 | ctx->digest_algo = HASH_ALGO_SHA384; | 101 | ctx->digest_algo = "sha384"; |
| 102 | break; | 102 | break; |
| 103 | case OID_sha512: | 103 | case OID_sha512: |
| 104 | ctx->digest_algo = HASH_ALGO_SHA512; | 104 | ctx->digest_algo = "sha512"; |
| 105 | break; | 105 | break; |
| 106 | case OID_sha224: | 106 | case OID_sha224: |
| 107 | ctx->digest_algo = HASH_ALGO_SHA224; | 107 | ctx->digest_algo = "sha224"; |
| 108 | break; | 108 | break; |
| 109 | 109 | ||
| 110 | case OID__NR: | 110 | case OID__NR: |
diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index cbbd03fd94f8..40de03f49ff8 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c | |||
| @@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, | |||
| 218 | 218 | ||
| 219 | switch (ctx->last_oid) { | 219 | switch (ctx->last_oid) { |
| 220 | case OID_md4: | 220 | case OID_md4: |
| 221 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4; | 221 | ctx->sinfo->sig.hash_algo = "md4"; |
| 222 | break; | 222 | break; |
| 223 | case OID_md5: | 223 | case OID_md5: |
| 224 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5; | 224 | ctx->sinfo->sig.hash_algo = "md5"; |
| 225 | break; | 225 | break; |
| 226 | case OID_sha1: | 226 | case OID_sha1: |
| 227 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1; | 227 | ctx->sinfo->sig.hash_algo = "sha1"; |
| 228 | break; | 228 | break; |
| 229 | case OID_sha256: | 229 | case OID_sha256: |
| 230 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; | 230 | ctx->sinfo->sig.hash_algo = "sha256"; |
| 231 | break; | 231 | break; |
| 232 | case OID_sha384: | 232 | case OID_sha384: |
| 233 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384; | 233 | ctx->sinfo->sig.hash_algo = "sha384"; |
| 234 | break; | 234 | break; |
| 235 | case OID_sha512: | 235 | case OID_sha512: |
| 236 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512; | 236 | ctx->sinfo->sig.hash_algo = "sha512"; |
| 237 | break; | 237 | break; |
| 238 | case OID_sha224: | 238 | case OID_sha224: |
| 239 | ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224; | 239 | ctx->sinfo->sig.hash_algo = "sha224"; |
| 240 | default: | 240 | default: |
| 241 | printk("Unsupported digest algo: %u\n", ctx->last_oid); | 241 | printk("Unsupported digest algo: %u\n", ctx->last_oid); |
| 242 | return -ENOPKG; | 242 | return -ENOPKG; |
| @@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, | |||
| 255 | 255 | ||
| 256 | switch (ctx->last_oid) { | 256 | switch (ctx->last_oid) { |
| 257 | case OID_rsaEncryption: | 257 | case OID_rsaEncryption: |
| 258 | ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA; | 258 | ctx->sinfo->sig.pkey_algo = "rsa"; |
| 259 | break; | 259 | break; |
| 260 | default: | 260 | default: |
| 261 | printk("Unsupported pkey algo: %u\n", ctx->last_oid); | 261 | printk("Unsupported pkey algo: %u\n", ctx->last_oid); |
| @@ -615,8 +615,6 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, | |||
| 615 | { | 615 | { |
| 616 | struct pkcs7_parse_context *ctx = context; | 616 | struct pkcs7_parse_context *ctx = context; |
| 617 | 617 | ||
| 618 | BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA); | ||
| 619 | |||
| 620 | ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL); | 618 | ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL); |
| 621 | if (!ctx->sinfo->sig.s) | 619 | if (!ctx->sinfo->sig.s) |
| 622 | return -ENOMEM; | 620 | return -ENOMEM; |
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index f5db1378c096..50be2a15e531 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c | |||
| @@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, | |||
| 31 | void *digest; | 31 | void *digest; |
| 32 | int ret; | 32 | int ret; |
| 33 | 33 | ||
| 34 | kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo); | 34 | kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo); |
| 35 | 35 | ||
| 36 | if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST || | 36 | if (!sinfo->sig.hash_algo) |
| 37 | !hash_algo_name[sinfo->sig.pkey_hash_algo]) | ||
| 38 | return -ENOPKG; | 37 | return -ENOPKG; |
| 39 | 38 | ||
| 40 | /* Allocate the hashing algorithm we're going to need and find out how | 39 | /* Allocate the hashing algorithm we're going to need and find out how |
| 41 | * big the hash operational data will be. | 40 | * big the hash operational data will be. |
| 42 | */ | 41 | */ |
| 43 | tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo], | 42 | tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0); |
| 44 | 0, 0); | ||
| 45 | if (IS_ERR(tfm)) | 43 | if (IS_ERR(tfm)) |
| 46 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); | 44 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); |
| 47 | 45 | ||
diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 27ebc2f44394..0f8b264b3961 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c | |||
| @@ -24,19 +24,6 @@ | |||
| 24 | 24 | ||
| 25 | MODULE_LICENSE("GPL"); | 25 | MODULE_LICENSE("GPL"); |
| 26 | 26 | ||
| 27 | const char *const pkey_algo_name[PKEY_ALGO__LAST] = { | ||
| 28 | [PKEY_ALGO_DSA] = "dsa", | ||
| 29 | [PKEY_ALGO_RSA] = "rsa", | ||
| 30 | }; | ||
| 31 | EXPORT_SYMBOL_GPL(pkey_algo_name); | ||
| 32 | |||
| 33 | const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { | ||
| 34 | [PKEY_ID_PGP] = "PGP", | ||
| 35 | [PKEY_ID_X509] = "X509", | ||
| 36 | [PKEY_ID_PKCS7] = "PKCS#7", | ||
| 37 | }; | ||
| 38 | EXPORT_SYMBOL_GPL(pkey_id_type_name); | ||
| 39 | |||
| 40 | /* | 27 | /* |
| 41 | * Provide a part of a description of the key for /proc/keys. | 28 | * Provide a part of a description of the key for /proc/keys. |
| 42 | */ | 29 | */ |
| @@ -46,9 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key, | |||
| 46 | struct public_key *key = asymmetric_key->payload.data[asym_crypto]; | 33 | struct public_key *key = asymmetric_key->payload.data[asym_crypto]; |
| 47 | 34 | ||
| 48 | if (key) | 35 | if (key) |
| 49 | seq_printf(m, "%s.%s", | 36 | seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); |
| 50 | pkey_id_type_name[key->id_type], | ||
| 51 | pkey_algo_name[key->pkey_algo]); | ||
| 52 | } | 37 | } |
| 53 | 38 | ||
| 54 | /* | 39 | /* |
| @@ -103,15 +88,14 @@ int public_key_verify_signature(const struct public_key *pkey, | |||
| 103 | BUG_ON(!sig->digest); | 88 | BUG_ON(!sig->digest); |
| 104 | BUG_ON(!sig->s); | 89 | BUG_ON(!sig->s); |
| 105 | 90 | ||
| 106 | alg_name = pkey_algo_name[sig->pkey_algo]; | 91 | alg_name = sig->pkey_algo; |
| 107 | if (sig->pkey_algo == PKEY_ALGO_RSA) { | 92 | if (strcmp(sig->pkey_algo, "rsa") == 0) { |
| 108 | /* The data wangled by the RSA algorithm is typically padded | 93 | /* The data wangled by the RSA algorithm is typically padded |
| 109 | * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 | 94 | * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 |
| 110 | * sec 8.2]. | 95 | * sec 8.2]. |
| 111 | */ | 96 | */ |
| 112 | if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, | 97 | if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, |
| 113 | "pkcs1pad(rsa,%s)", | 98 | "pkcs1pad(rsa,%s)", sig->hash_algo |
| 114 | hash_algo_name[sig->pkey_hash_algo] | ||
| 115 | ) >= CRYPTO_MAX_ALG_NAME) | 99 | ) >= CRYPTO_MAX_ALG_NAME) |
| 116 | return -EINVAL; | 100 | return -EINVAL; |
| 117 | alg_name = alg_name_buf; | 101 | alg_name = alg_name_buf; |
diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 897b734dabf9..7e8c2338ae25 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c | |||
| @@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, | |||
| 328 | void *digest; | 328 | void *digest; |
| 329 | int ret; | 329 | int ret; |
| 330 | 330 | ||
| 331 | kenter(",%u", ctx->digest_algo); | 331 | kenter(",%s", ctx->digest_algo); |
| 332 | 332 | ||
| 333 | /* Allocate the hashing algorithm we're going to need and find out how | 333 | /* Allocate the hashing algorithm we're going to need and find out how |
| 334 | * big the hash operational data will be. | 334 | * big the hash operational data will be. |
| 335 | */ | 335 | */ |
| 336 | tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0); | 336 | tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0); |
| 337 | if (IS_ERR(tfm)) | 337 | if (IS_ERR(tfm)) |
| 338 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); | 338 | return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); |
| 339 | 339 | ||
diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h index 55d5f7ebc45a..a133eb81a492 100644 --- a/crypto/asymmetric_keys/verify_pefile.h +++ b/crypto/asymmetric_keys/verify_pefile.h | |||
| @@ -28,7 +28,7 @@ struct pefile_context { | |||
| 28 | /* PKCS#7 MS Individual Code Signing content */ | 28 | /* PKCS#7 MS Individual Code Signing content */ |
| 29 | const void *digest; /* Digest */ | 29 | const void *digest; /* Digest */ |
| 30 | unsigned digest_len; /* Digest length */ | 30 | unsigned digest_len; /* Digest length */ |
| 31 | enum hash_algo digest_algo; /* Digest algorithm */ | 31 | const char *digest_algo; /* Digest algorithm */ |
| 32 | }; | 32 | }; |
| 33 | 33 | ||
| 34 | #define kenter(FMT, ...) \ | 34 | #define kenter(FMT, ...) \ |
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index c02c200a7136..4a29bac70060 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c | |||
| @@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, | |||
| 188 | return -ENOPKG; /* Unsupported combination */ | 188 | return -ENOPKG; /* Unsupported combination */ |
| 189 | 189 | ||
| 190 | case OID_md4WithRSAEncryption: | 190 | case OID_md4WithRSAEncryption: |
| 191 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5; | 191 | ctx->cert->sig.hash_algo = "md4"; |
| 192 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 192 | ctx->cert->sig.pkey_algo = "rsa"; |
| 193 | break; | 193 | break; |
| 194 | 194 | ||
| 195 | case OID_sha1WithRSAEncryption: | 195 | case OID_sha1WithRSAEncryption: |
| 196 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1; | 196 | ctx->cert->sig.hash_algo = "sha1"; |
| 197 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 197 | ctx->cert->sig.pkey_algo = "rsa"; |
| 198 | break; | 198 | break; |
| 199 | 199 | ||
| 200 | case OID_sha256WithRSAEncryption: | 200 | case OID_sha256WithRSAEncryption: |
| 201 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256; | 201 | ctx->cert->sig.hash_algo = "sha256"; |
| 202 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 202 | ctx->cert->sig.pkey_algo = "rsa"; |
| 203 | break; | 203 | break; |
| 204 | 204 | ||
| 205 | case OID_sha384WithRSAEncryption: | 205 | case OID_sha384WithRSAEncryption: |
| 206 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384; | 206 | ctx->cert->sig.hash_algo = "sha384"; |
| 207 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 207 | ctx->cert->sig.pkey_algo = "rsa"; |
| 208 | break; | 208 | break; |
| 209 | 209 | ||
| 210 | case OID_sha512WithRSAEncryption: | 210 | case OID_sha512WithRSAEncryption: |
| 211 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512; | 211 | ctx->cert->sig.hash_algo = "sha512"; |
| 212 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 212 | ctx->cert->sig.pkey_algo = "rsa"; |
| 213 | break; | 213 | break; |
| 214 | 214 | ||
| 215 | case OID_sha224WithRSAEncryption: | 215 | case OID_sha224WithRSAEncryption: |
| 216 | ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224; | 216 | ctx->cert->sig.hash_algo = "sha224"; |
| 217 | ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; | 217 | ctx->cert->sig.pkey_algo = "rsa"; |
| 218 | break; | 218 | break; |
| 219 | } | 219 | } |
| 220 | 220 | ||
| @@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen, | |||
| 396 | if (ctx->last_oid != OID_rsaEncryption) | 396 | if (ctx->last_oid != OID_rsaEncryption) |
| 397 | return -ENOPKG; | 397 | return -ENOPKG; |
| 398 | 398 | ||
| 399 | ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; | 399 | ctx->cert->pub->pkey_algo = "rsa"; |
| 400 | 400 | ||
| 401 | /* Discard the BIT STRING metadata */ | 401 | /* Discard the BIT STRING metadata */ |
| 402 | ctx->key = value + 1; | 402 | ctx->key = value + 1; |
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 7092d5cbb5d3..733c046aacc6 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c | |||
| @@ -176,7 +176,7 @@ int x509_get_sig_params(struct x509_certificate *cert) | |||
| 176 | /* Allocate the hashing algorithm we're going to need and find out how | 176 | /* Allocate the hashing algorithm we're going to need and find out how |
| 177 | * big the hash operational data will be. | 177 | * big the hash operational data will be. |
| 178 | */ | 178 | */ |
| 179 | tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); | 179 | tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0); |
| 180 | if (IS_ERR(tfm)) { | 180 | if (IS_ERR(tfm)) { |
| 181 | if (PTR_ERR(tfm) == -ENOENT) { | 181 | if (PTR_ERR(tfm) == -ENOENT) { |
| 182 | cert->unsupported_crypto = true; | 182 | cert->unsupported_crypto = true; |
| @@ -291,21 +291,20 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) | |||
| 291 | pr_devel("Cert Issuer: %s\n", cert->issuer); | 291 | pr_devel("Cert Issuer: %s\n", cert->issuer); |
| 292 | pr_devel("Cert Subject: %s\n", cert->subject); | 292 | pr_devel("Cert Subject: %s\n", cert->subject); |
| 293 | 293 | ||
| 294 | if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || | 294 | if (!cert->pub->pkey_algo || |
| 295 | cert->sig.pkey_algo >= PKEY_ALGO__LAST || | 295 | !cert->sig.pkey_algo || |
| 296 | cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || | 296 | !cert->sig.hash_algo) { |
| 297 | !hash_algo_name[cert->sig.pkey_hash_algo]) { | ||
| 298 | ret = -ENOPKG; | 297 | ret = -ENOPKG; |
| 299 | goto error_free_cert; | 298 | goto error_free_cert; |
| 300 | } | 299 | } |
| 301 | 300 | ||
| 302 | pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); | 301 | pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); |
| 303 | pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); | 302 | pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); |
| 304 | pr_devel("Cert Signature: %s + %s\n", | 303 | pr_devel("Cert Signature: %s + %s\n", |
| 305 | pkey_algo_name[cert->sig.pkey_algo], | 304 | cert->sig.pkey_algo, |
| 306 | hash_algo_name[cert->sig.pkey_hash_algo]); | 305 | cert->sig.hash_algo); |
| 307 | 306 | ||
| 308 | cert->pub->id_type = PKEY_ID_X509; | 307 | cert->pub->id_type = "X509"; |
| 309 | 308 | ||
| 310 | /* Check the signature on the key if it appears to be self-signed */ | 309 | /* Check the signature on the key if it appears to be self-signed */ |
| 311 | if ((!cert->akid_skid && !cert->akid_id) || | 310 | if ((!cert->akid_skid && !cert->akid_id) || |
