diff options
-rw-r--r-- | crypto/aead.c | 152 | ||||
-rw-r--r-- | include/crypto/aead.h | 44 | ||||
-rw-r--r-- | include/crypto/internal/aead.h | 36 |
3 files changed, 213 insertions, 19 deletions
diff --git a/crypto/aead.c b/crypto/aead.c index ebc91ea89c91..d231e2837bfd 100644 --- a/crypto/aead.c +++ b/crypto/aead.c | |||
@@ -33,7 +33,6 @@ static int aead_null_givdecrypt(struct aead_givcrypt_request *req); | |||
33 | static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, | 33 | static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, |
34 | unsigned int keylen) | 34 | unsigned int keylen) |
35 | { | 35 | { |
36 | struct old_aead_alg *aead = crypto_old_aead_alg(tfm); | ||
37 | unsigned long alignmask = crypto_aead_alignmask(tfm); | 36 | unsigned long alignmask = crypto_aead_alignmask(tfm); |
38 | int ret; | 37 | int ret; |
39 | u8 *buffer, *alignbuffer; | 38 | u8 *buffer, *alignbuffer; |
@@ -46,7 +45,7 @@ static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, | |||
46 | 45 | ||
47 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); | 46 | alignbuffer = (u8 *)ALIGN((unsigned long)buffer, alignmask + 1); |
48 | memcpy(alignbuffer, key, keylen); | 47 | memcpy(alignbuffer, key, keylen); |
49 | ret = aead->setkey(tfm, alignbuffer, keylen); | 48 | ret = tfm->setkey(tfm, alignbuffer, keylen); |
50 | memset(alignbuffer, 0, keylen); | 49 | memset(alignbuffer, 0, keylen); |
51 | kfree(buffer); | 50 | kfree(buffer); |
52 | return ret; | 51 | return ret; |
@@ -55,7 +54,6 @@ static int setkey_unaligned(struct crypto_aead *tfm, const u8 *key, | |||
55 | int crypto_aead_setkey(struct crypto_aead *tfm, | 54 | int crypto_aead_setkey(struct crypto_aead *tfm, |
56 | const u8 *key, unsigned int keylen) | 55 | const u8 *key, unsigned int keylen) |
57 | { | 56 | { |
58 | struct old_aead_alg *aead = crypto_old_aead_alg(tfm); | ||
59 | unsigned long alignmask = crypto_aead_alignmask(tfm); | 57 | unsigned long alignmask = crypto_aead_alignmask(tfm); |
60 | 58 | ||
61 | tfm = tfm->child; | 59 | tfm = tfm->child; |
@@ -63,7 +61,7 @@ int crypto_aead_setkey(struct crypto_aead *tfm, | |||
63 | if ((unsigned long)key & alignmask) | 61 | if ((unsigned long)key & alignmask) |
64 | return setkey_unaligned(tfm, key, keylen); | 62 | return setkey_unaligned(tfm, key, keylen); |
65 | 63 | ||
66 | return aead->setkey(tfm, key, keylen); | 64 | return tfm->setkey(tfm, key, keylen); |
67 | } | 65 | } |
68 | EXPORT_SYMBOL_GPL(crypto_aead_setkey); | 66 | EXPORT_SYMBOL_GPL(crypto_aead_setkey); |
69 | 67 | ||
@@ -71,12 +69,11 @@ int crypto_aead_setauthsize(struct crypto_aead *tfm, unsigned int authsize) | |||
71 | { | 69 | { |
72 | int err; | 70 | int err; |
73 | 71 | ||
74 | if (authsize > crypto_old_aead_alg(tfm)->maxauthsize) | 72 | if (authsize > tfm->maxauthsize) |
75 | return -EINVAL; | 73 | return -EINVAL; |
76 | 74 | ||
77 | if (crypto_old_aead_alg(tfm)->setauthsize) { | 75 | if (tfm->setauthsize) { |
78 | err = crypto_old_aead_alg(tfm)->setauthsize( | 76 | err = tfm->setauthsize(tfm->child, authsize); |
79 | tfm->child, authsize); | ||
80 | if (err) | 77 | if (err) |
81 | return err; | 78 | return err; |
82 | } | 79 | } |
@@ -145,7 +142,7 @@ static int no_givcrypt(struct aead_givcrypt_request *req) | |||
145 | return -ENOSYS; | 142 | return -ENOSYS; |
146 | } | 143 | } |
147 | 144 | ||
148 | static int crypto_aead_init_tfm(struct crypto_tfm *tfm) | 145 | static int crypto_old_aead_init_tfm(struct crypto_tfm *tfm) |
149 | { | 146 | { |
150 | struct old_aead_alg *alg = &tfm->__crt_alg->cra_aead; | 147 | struct old_aead_alg *alg = &tfm->__crt_alg->cra_aead; |
151 | struct crypto_aead *crt = __crypto_aead_cast(tfm); | 148 | struct crypto_aead *crt = __crypto_aead_cast(tfm); |
@@ -153,6 +150,8 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm) | |||
153 | if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) | 150 | if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) |
154 | return -EINVAL; | 151 | return -EINVAL; |
155 | 152 | ||
153 | crt->setkey = alg->setkey; | ||
154 | crt->setauthsize = alg->setauthsize; | ||
156 | crt->encrypt = old_encrypt; | 155 | crt->encrypt = old_encrypt; |
157 | crt->decrypt = old_decrypt; | 156 | crt->decrypt = old_decrypt; |
158 | if (alg->ivsize) { | 157 | if (alg->ivsize) { |
@@ -164,13 +163,34 @@ static int crypto_aead_init_tfm(struct crypto_tfm *tfm) | |||
164 | } | 163 | } |
165 | crt->child = __crypto_aead_cast(tfm); | 164 | crt->child = __crypto_aead_cast(tfm); |
166 | crt->ivsize = alg->ivsize; | 165 | crt->ivsize = alg->ivsize; |
166 | crt->maxauthsize = alg->maxauthsize; | ||
167 | crt->authsize = alg->maxauthsize; | 167 | crt->authsize = alg->maxauthsize; |
168 | 168 | ||
169 | return 0; | 169 | return 0; |
170 | } | 170 | } |
171 | 171 | ||
172 | static int crypto_aead_init_tfm(struct crypto_tfm *tfm) | ||
173 | { | ||
174 | struct crypto_aead *aead = __crypto_aead_cast(tfm); | ||
175 | struct aead_alg *alg = crypto_aead_alg(aead); | ||
176 | |||
177 | if (crypto_old_aead_alg(aead)->encrypt) | ||
178 | return crypto_old_aead_init_tfm(tfm); | ||
179 | |||
180 | aead->setkey = alg->setkey; | ||
181 | aead->setauthsize = alg->setauthsize; | ||
182 | aead->encrypt = alg->encrypt; | ||
183 | aead->decrypt = alg->decrypt; | ||
184 | aead->child = __crypto_aead_cast(tfm); | ||
185 | aead->ivsize = alg->ivsize; | ||
186 | aead->maxauthsize = alg->maxauthsize; | ||
187 | aead->authsize = alg->maxauthsize; | ||
188 | |||
189 | return 0; | ||
190 | } | ||
191 | |||
172 | #ifdef CONFIG_NET | 192 | #ifdef CONFIG_NET |
173 | static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) | 193 | static int crypto_old_aead_report(struct sk_buff *skb, struct crypto_alg *alg) |
174 | { | 194 | { |
175 | struct crypto_report_aead raead; | 195 | struct crypto_report_aead raead; |
176 | struct old_aead_alg *aead = &alg->cra_aead; | 196 | struct old_aead_alg *aead = &alg->cra_aead; |
@@ -191,15 +211,15 @@ nla_put_failure: | |||
191 | return -EMSGSIZE; | 211 | return -EMSGSIZE; |
192 | } | 212 | } |
193 | #else | 213 | #else |
194 | static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) | 214 | static int crypto_old_aead_report(struct sk_buff *skb, struct crypto_alg *alg) |
195 | { | 215 | { |
196 | return -ENOSYS; | 216 | return -ENOSYS; |
197 | } | 217 | } |
198 | #endif | 218 | #endif |
199 | 219 | ||
200 | static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) | 220 | static void crypto_old_aead_show(struct seq_file *m, struct crypto_alg *alg) |
201 | __attribute__ ((unused)); | 221 | __attribute__ ((unused)); |
202 | static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) | 222 | static void crypto_old_aead_show(struct seq_file *m, struct crypto_alg *alg) |
203 | { | 223 | { |
204 | struct old_aead_alg *aead = &alg->cra_aead; | 224 | struct old_aead_alg *aead = &alg->cra_aead; |
205 | 225 | ||
@@ -216,9 +236,9 @@ const struct crypto_type crypto_aead_type = { | |||
216 | .extsize = crypto_alg_extsize, | 236 | .extsize = crypto_alg_extsize, |
217 | .init_tfm = crypto_aead_init_tfm, | 237 | .init_tfm = crypto_aead_init_tfm, |
218 | #ifdef CONFIG_PROC_FS | 238 | #ifdef CONFIG_PROC_FS |
219 | .show = crypto_aead_show, | 239 | .show = crypto_old_aead_show, |
220 | #endif | 240 | #endif |
221 | .report = crypto_aead_report, | 241 | .report = crypto_old_aead_report, |
222 | .lookup = crypto_lookup_aead, | 242 | .lookup = crypto_lookup_aead, |
223 | .maskclear = ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV), | 243 | .maskclear = ~(CRYPTO_ALG_TYPE_MASK | CRYPTO_ALG_GENIV), |
224 | .maskset = CRYPTO_ALG_TYPE_MASK, | 244 | .maskset = CRYPTO_ALG_TYPE_MASK, |
@@ -227,6 +247,62 @@ const struct crypto_type crypto_aead_type = { | |||
227 | }; | 247 | }; |
228 | EXPORT_SYMBOL_GPL(crypto_aead_type); | 248 | EXPORT_SYMBOL_GPL(crypto_aead_type); |
229 | 249 | ||
250 | #ifdef CONFIG_NET | ||
251 | static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) | ||
252 | { | ||
253 | struct crypto_report_aead raead; | ||
254 | struct aead_alg *aead = container_of(alg, struct aead_alg, base); | ||
255 | |||
256 | strncpy(raead.type, "aead", sizeof(raead.type)); | ||
257 | strncpy(raead.geniv, "<none>", sizeof(raead.geniv)); | ||
258 | |||
259 | raead.blocksize = alg->cra_blocksize; | ||
260 | raead.maxauthsize = aead->maxauthsize; | ||
261 | raead.ivsize = aead->ivsize; | ||
262 | |||
263 | if (nla_put(skb, CRYPTOCFGA_REPORT_AEAD, | ||
264 | sizeof(struct crypto_report_aead), &raead)) | ||
265 | goto nla_put_failure; | ||
266 | return 0; | ||
267 | |||
268 | nla_put_failure: | ||
269 | return -EMSGSIZE; | ||
270 | } | ||
271 | #else | ||
272 | static int crypto_aead_report(struct sk_buff *skb, struct crypto_alg *alg) | ||
273 | { | ||
274 | return -ENOSYS; | ||
275 | } | ||
276 | #endif | ||
277 | |||
278 | static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) | ||
279 | __attribute__ ((unused)); | ||
280 | static void crypto_aead_show(struct seq_file *m, struct crypto_alg *alg) | ||
281 | { | ||
282 | struct aead_alg *aead = container_of(alg, struct aead_alg, base); | ||
283 | |||
284 | seq_printf(m, "type : aead\n"); | ||
285 | seq_printf(m, "async : %s\n", alg->cra_flags & CRYPTO_ALG_ASYNC ? | ||
286 | "yes" : "no"); | ||
287 | seq_printf(m, "blocksize : %u\n", alg->cra_blocksize); | ||
288 | seq_printf(m, "ivsize : %u\n", aead->ivsize); | ||
289 | seq_printf(m, "maxauthsize : %u\n", aead->maxauthsize); | ||
290 | seq_printf(m, "geniv : <none>\n"); | ||
291 | } | ||
292 | |||
293 | static const struct crypto_type crypto_new_aead_type = { | ||
294 | .extsize = crypto_alg_extsize, | ||
295 | .init_tfm = crypto_aead_init_tfm, | ||
296 | #ifdef CONFIG_PROC_FS | ||
297 | .show = crypto_aead_show, | ||
298 | #endif | ||
299 | .report = crypto_aead_report, | ||
300 | .maskclear = ~CRYPTO_ALG_TYPE_MASK, | ||
301 | .maskset = CRYPTO_ALG_TYPE_MASK, | ||
302 | .type = CRYPTO_ALG_TYPE_AEAD, | ||
303 | .tfmsize = offsetof(struct crypto_aead, base), | ||
304 | }; | ||
305 | |||
230 | static int aead_null_givencrypt(struct aead_givcrypt_request *req) | 306 | static int aead_null_givencrypt(struct aead_givcrypt_request *req) |
231 | { | 307 | { |
232 | return crypto_aead_encrypt(&req->areq); | 308 | return crypto_aead_encrypt(&req->areq); |
@@ -552,5 +628,51 @@ struct crypto_aead *crypto_alloc_aead(const char *alg_name, u32 type, u32 mask) | |||
552 | } | 628 | } |
553 | EXPORT_SYMBOL_GPL(crypto_alloc_aead); | 629 | EXPORT_SYMBOL_GPL(crypto_alloc_aead); |
554 | 630 | ||
631 | static int aead_prepare_alg(struct aead_alg *alg) | ||
632 | { | ||
633 | struct crypto_alg *base = &alg->base; | ||
634 | |||
635 | if (max(alg->maxauthsize, alg->ivsize) > PAGE_SIZE / 8) | ||
636 | return -EINVAL; | ||
637 | |||
638 | base->cra_type = &crypto_new_aead_type; | ||
639 | base->cra_flags &= ~CRYPTO_ALG_TYPE_MASK; | ||
640 | base->cra_flags |= CRYPTO_ALG_TYPE_AEAD; | ||
641 | |||
642 | return 0; | ||
643 | } | ||
644 | |||
645 | int crypto_register_aead(struct aead_alg *alg) | ||
646 | { | ||
647 | struct crypto_alg *base = &alg->base; | ||
648 | int err; | ||
649 | |||
650 | err = aead_prepare_alg(alg); | ||
651 | if (err) | ||
652 | return err; | ||
653 | |||
654 | return crypto_register_alg(base); | ||
655 | } | ||
656 | EXPORT_SYMBOL_GPL(crypto_register_aead); | ||
657 | |||
658 | int crypto_unregister_aead(struct aead_alg *alg) | ||
659 | { | ||
660 | return crypto_unregister_alg(&alg->base); | ||
661 | } | ||
662 | EXPORT_SYMBOL_GPL(crypto_unregister_aead); | ||
663 | |||
664 | int aead_register_instance(struct crypto_template *tmpl, | ||
665 | struct aead_instance *inst) | ||
666 | { | ||
667 | int err; | ||
668 | |||
669 | err = aead_prepare_alg(&inst->alg); | ||
670 | if (err) | ||
671 | return err; | ||
672 | |||
673 | return crypto_register_instance(tmpl, aead_crypto_instance(inst)); | ||
674 | } | ||
675 | EXPORT_SYMBOL_GPL(aead_register_instance); | ||
676 | |||
555 | MODULE_LICENSE("GPL"); | 677 | MODULE_LICENSE("GPL"); |
556 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); | 678 | MODULE_DESCRIPTION("Authenticated Encryption with Associated Data (AEAD)"); |
diff --git a/include/crypto/aead.h b/include/crypto/aead.h index aebf57dfb903..177e6f46e2bb 100644 --- a/include/crypto/aead.h +++ b/include/crypto/aead.h | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <linux/kernel.h> | 17 | #include <linux/kernel.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | 19 | ||
20 | #define aead_alg old_aead_alg | ||
21 | |||
22 | /** | 20 | /** |
23 | * DOC: Authenticated Encryption With Associated Data (AEAD) Cipher API | 21 | * DOC: Authenticated Encryption With Associated Data (AEAD) Cipher API |
24 | * | 22 | * |
@@ -92,7 +90,48 @@ struct aead_givcrypt_request { | |||
92 | struct aead_request areq; | 90 | struct aead_request areq; |
93 | }; | 91 | }; |
94 | 92 | ||
93 | /** | ||
94 | * struct aead_alg - AEAD cipher definition | ||
95 | * @maxauthsize: Set the maximum authentication tag size supported by the | ||
96 | * transformation. A transformation may support smaller tag sizes. | ||
97 | * As the authentication tag is a message digest to ensure the | ||
98 | * integrity of the encrypted data, a consumer typically wants the | ||
99 | * largest authentication tag possible as defined by this | ||
100 | * variable. | ||
101 | * @setauthsize: Set authentication size for the AEAD transformation. This | ||
102 | * function is used to specify the consumer requested size of the | ||
103 | * authentication tag to be either generated by the transformation | ||
104 | * during encryption or the size of the authentication tag to be | ||
105 | * supplied during the decryption operation. This function is also | ||
106 | * responsible for checking the authentication tag size for | ||
107 | * validity. | ||
108 | * @setkey: see struct ablkcipher_alg | ||
109 | * @encrypt: see struct ablkcipher_alg | ||
110 | * @decrypt: see struct ablkcipher_alg | ||
111 | * @geniv: see struct ablkcipher_alg | ||
112 | * @ivsize: see struct ablkcipher_alg | ||
113 | * | ||
114 | * All fields except @ivsize is mandatory and must be filled. | ||
115 | */ | ||
116 | struct aead_alg { | ||
117 | int (*setkey)(struct crypto_aead *tfm, const u8 *key, | ||
118 | unsigned int keylen); | ||
119 | int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize); | ||
120 | int (*encrypt)(struct aead_request *req); | ||
121 | int (*decrypt)(struct aead_request *req); | ||
122 | |||
123 | const char *geniv; | ||
124 | |||
125 | unsigned int ivsize; | ||
126 | unsigned int maxauthsize; | ||
127 | |||
128 | struct crypto_alg base; | ||
129 | }; | ||
130 | |||
95 | struct crypto_aead { | 131 | struct crypto_aead { |
132 | int (*setkey)(struct crypto_aead *tfm, const u8 *key, | ||
133 | unsigned int keylen); | ||
134 | int (*setauthsize)(struct crypto_aead *tfm, unsigned int authsize); | ||
96 | int (*encrypt)(struct aead_request *req); | 135 | int (*encrypt)(struct aead_request *req); |
97 | int (*decrypt)(struct aead_request *req); | 136 | int (*decrypt)(struct aead_request *req); |
98 | int (*givencrypt)(struct aead_givcrypt_request *req); | 137 | int (*givencrypt)(struct aead_givcrypt_request *req); |
@@ -102,6 +141,7 @@ struct crypto_aead { | |||
102 | 141 | ||
103 | unsigned int ivsize; | 142 | unsigned int ivsize; |
104 | unsigned int authsize; | 143 | unsigned int authsize; |
144 | unsigned int maxauthsize; | ||
105 | unsigned int reqsize; | 145 | unsigned int reqsize; |
106 | 146 | ||
107 | struct crypto_tfm base; | 147 | struct crypto_tfm base; |
diff --git a/include/crypto/internal/aead.h b/include/crypto/internal/aead.h index 4614f795f8bc..6cd31519c4f6 100644 --- a/include/crypto/internal/aead.h +++ b/include/crypto/internal/aead.h | |||
@@ -19,6 +19,10 @@ | |||
19 | 19 | ||
20 | struct rtattr; | 20 | struct rtattr; |
21 | 21 | ||
22 | struct aead_instance { | ||
23 | struct aead_alg alg; | ||
24 | }; | ||
25 | |||
22 | struct crypto_aead_spawn { | 26 | struct crypto_aead_spawn { |
23 | struct crypto_spawn base; | 27 | struct crypto_spawn base; |
24 | }; | 28 | }; |
@@ -33,7 +37,8 @@ static inline struct old_aead_alg *crypto_old_aead_alg(struct crypto_aead *tfm) | |||
33 | 37 | ||
34 | static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm) | 38 | static inline struct aead_alg *crypto_aead_alg(struct crypto_aead *tfm) |
35 | { | 39 | { |
36 | return &crypto_aead_tfm(tfm)->__crt_alg->cra_aead; | 40 | return container_of(crypto_aead_tfm(tfm)->__crt_alg, |
41 | struct aead_alg, base); | ||
37 | } | 42 | } |
38 | 43 | ||
39 | static inline void *crypto_aead_ctx(struct crypto_aead *tfm) | 44 | static inline void *crypto_aead_ctx(struct crypto_aead *tfm) |
@@ -47,6 +52,22 @@ static inline struct crypto_instance *crypto_aead_alg_instance( | |||
47 | return crypto_tfm_alg_instance(&aead->base); | 52 | return crypto_tfm_alg_instance(&aead->base); |
48 | } | 53 | } |
49 | 54 | ||
55 | static inline struct crypto_instance *aead_crypto_instance( | ||
56 | struct aead_instance *inst) | ||
57 | { | ||
58 | return container_of(&inst->alg.base, struct crypto_instance, alg); | ||
59 | } | ||
60 | |||
61 | static inline struct aead_instance *aead_instance(struct crypto_instance *inst) | ||
62 | { | ||
63 | return container_of(&inst->alg, struct aead_instance, alg.base); | ||
64 | } | ||
65 | |||
66 | static inline void *aead_instance_ctx(struct aead_instance *inst) | ||
67 | { | ||
68 | return crypto_instance_ctx(aead_crypto_instance(inst)); | ||
69 | } | ||
70 | |||
50 | static inline void *aead_request_ctx(struct aead_request *req) | 71 | static inline void *aead_request_ctx(struct aead_request *req) |
51 | { | 72 | { |
52 | return req->__ctx; | 73 | return req->__ctx; |
@@ -84,6 +105,12 @@ static inline struct crypto_alg *crypto_aead_spawn_alg( | |||
84 | return spawn->base.alg; | 105 | return spawn->base.alg; |
85 | } | 106 | } |
86 | 107 | ||
108 | static inline struct aead_alg *crypto_spawn_aead_alg( | ||
109 | struct crypto_aead_spawn *spawn) | ||
110 | { | ||
111 | return container_of(spawn->base.alg, struct aead_alg, base); | ||
112 | } | ||
113 | |||
87 | static inline struct crypto_aead *crypto_spawn_aead( | 114 | static inline struct crypto_aead *crypto_spawn_aead( |
88 | struct crypto_aead_spawn *spawn) | 115 | struct crypto_aead_spawn *spawn) |
89 | { | 116 | { |
@@ -121,8 +148,13 @@ static inline void crypto_aead_set_reqsize(struct crypto_aead *aead, | |||
121 | 148 | ||
122 | static inline unsigned int crypto_aead_maxauthsize(struct crypto_aead *aead) | 149 | static inline unsigned int crypto_aead_maxauthsize(struct crypto_aead *aead) |
123 | { | 150 | { |
124 | return crypto_old_aead_alg(aead)->maxauthsize; | 151 | return aead->maxauthsize; |
125 | } | 152 | } |
126 | 153 | ||
154 | int crypto_register_aead(struct aead_alg *alg); | ||
155 | int crypto_unregister_aead(struct aead_alg *alg); | ||
156 | int aead_register_instance(struct crypto_template *tmpl, | ||
157 | struct aead_instance *inst); | ||
158 | |||
127 | #endif /* _CRYPTO_INTERNAL_AEAD_H */ | 159 | #endif /* _CRYPTO_INTERNAL_AEAD_H */ |
128 | 160 | ||