| SYSTEMD-CRYPTENROLL(1) | systemd-cryptenroll | SYSTEMD-CRYPTENROLL(1) |
نام (NAME)
systemd-cryptenroll - ثبت کلیدها و ماژولهای امنیتی سختافزاری در پارتیشنهای رمزگذاریشده LUKS2
خلاصه دستور (SYNOPSIS)
systemd-cryptenroll [OPTIONS...] [DEVICE]
توضیحات (DESCRIPTION)
systemd-cryptenroll ابزاری برای ثبت توکنها و دستگاههای امنیتی سختافزاری در یک حجم رمزگذاریشده با LUKS2 است، که سپس میتوان از آنها برای باز کردن قفل حجم در حین بوت سیستم استفاده کرد. بهطور مشخص، از ثبت توکنها و اعتبارنامههای زیر پشتیبانی میکند:
علاوه بر این، میتوان از این ابزار برای شمارش توکنهای امنیتی ثبتشده فعلی و پاک کردن (wipe) زیرمجموعهای از آنها استفاده کرد. عملیات پاک کردن را میتوان با عملیات ثبت یک توکن امنیتی جدید ترکیب نمود تا ثبتها بهروزرسانی یا جایگزین شوند.
این ابزار تنها از حجمهای LUKS2 پشتیبانی میکند، زیرا متادادههای توکن را در ناحیه توکن JSON در LUKS2 ذخیره مینماید که در سایر فرمتهای رمزگذاری در دسترس نیست.
اگر هیچ دستگاهی بهطور صریح مشخص نشود و هیچ عملیات پاکسازی نیز درخواست نشده باشد، systemd-cryptsetup روی دستگاه پشتیبان /var/ عمل میکند. (توجه داشته باشید در حالت معمول که /var/ روی همان سیستمفایل ریشه قرار دارد، در نتیجه این دستور کلیدی را در دستگاه پشتیبان سیستمفایل ریشه ثبت مینماید.)
رجیسترهای PCR و خطمشیهای TPM2
رجیسترهای PCR امکان مقید کردن رمزگذاری اسرار به نگارشهای مشخصی از نرمافزار و وضعیت سیستم را فراهم میسازند، بهطوری که کلید ثبتشده تنها در صورتی قابل دسترس باشد (اصطلاحاً "unseal" شود) که نرمافزار و/یا پیکربندی معتمد مشخصی استفاده شود. چنین پیوندهایی را میتوان با گزینه --tpm2-pcrs= که در زیر توضیح داده شده ایجاد کرد.
همچنین میتوان اسرار را بهطور غیرمستقیم مقید ساخت: یک خطمشی امضاشده برای وضعیتی از ترکیب مقادیر PCR ارائه میشود، و رمز به بخش عمومی کلیدی که برای امضای این خطمشی به کار رفته مقید میگردد. این بدان معناست که مالک یک کلید میتواند توالی از خطمشیهای امضاشده را برای نگارشهای مشخصی از نرمافزار و وضعیتهای سیستم تولید کند، و تا زمانی که وضعیت ماشین با یکی از آن خطمشیها همخوانی داشته باشد، رمز قابل رمزگشایی خواهد بود. برای نمونه، یک توزیعکننده میتواند چنین خطمشیای را برای هر بهروزرسانی kernel+initrd ارائه دهد، که به کاربران اجازه میدهد اسرار را بهگونهای رمزگذاری کنند که هنگام اجرای هر kernel+initrd امضاشده توسط آن توزیعکننده رمزگشایی شوند. چنین پیوندهایی را میتوان با گزینههای --tpm2-public-key=، --tpm2-public-key-pcrs= و --tpm2-signature= که در زیر توضیح داده شدهاند ایجاد نمود.
برای مشاهده فهرست رسمی PCRها و چگونگی بهروزرسانی آنها، به UAPI.7 Linux TPM PCR Registry[1] مراجعه کنید. جدول زیر حاوی یک راهنمای مرجع سریع است که بهویژه PCRهای اصلاحشده توسط systemd را تشریح مینماید.
Table 1. Well-known PCR Definitions
| PCR | نام | توضیحات |
| 0 | platform-code | کد اجرایی میانافزار اصلی سیستم؛ با بهروزرسانیهای میانافزار تغییر میکند |
| 1 | platform-config | دادههای میانافزار اصلی سیستم/پیکربندی پلتفرم میزبان؛ معمولاً حاوی شمارهسریال و مدل بوده و با تعویض سختافزار پایه/پردازنده/رم تغییر میکند |
| 2 | external-code | کد اجرایی توسعهیافته یا اتصالپذیر؛ شامل Option ROMها روی سختافزارهای اتصالپذیر |
| 3 | external-config | دادههای میانافزار توسعهیافته یا اتصالپذیر؛ شامل اطلاعات سختافزارهای اتصالپذیر |
| 4 | boot-loader-code | بوتلودر و درایورهای اضافی، باینریهای PE که توسط بوتلودر فراخوانی میشوند؛ با بهروزرسانیهای بوتلودر تغییر میکند. همچنین sd-stub(7) ایمیجهای توسعه سیستم خواندهشده از ESP را در اینجا اندازهگیری میکند (به systemd-sysext(8) مراجعه کنید). |
| 5 | boot-loader-config | جدول پارتیشن/GPT؛ هنگامی که پارتیشنها افزوده، تغییر داده یا حذف شوند تغییر مییابد |
| 7 | secure-boot-policy | وضعیت بوت امن (Secure Boot)؛ هنگامی که حالت UEFI SecureBoot فعال/غیرفعال شود یا گواهیهای میانافزار (PK، KEK، db، dbx و ...) تغییر کنند، تغییر مییابد. |
| 9 | kernel-initrd | کرنل لینوکس تمام initrdهایی را که دریافت میکند در این PCR اندازهگیری مینماید. |
| 10 | ima | پروژه IMA وضعیت زمان اجرای خود را در این PCR اندازهگیری میکند. |
| 11 | kernel-boot | systemd-stub(7) ایمیج هسته ELF، initrd تعبیهشده و سایر محمولههای ایمیج PE را که در آن قرار گرفته است در این PCR اندازهگیری میکند. همچنین systemd-pcrphase.service(8) رشتههای مراحل مختلف بوت را در نقاط عطف گوناگون فرآیند بوت در این PCR اندازه میگیرد. |
| 12 | kernel-config | systemd-boot(7) خط فرمان کرنل را در این PCR اندازهگیری میکند. systemd-stub(7) هرگونه خط فرمان کرنل دستی مشخصشده (یعنی خط فرمان کرنلی که جایگزین خط فرمان تعبیهشده در ایمیج یکپارچه PE میشود) و اعتبارنامههای بارگذاریشده را در این PCR اندازه میگیرد. |
| 13 | sysexts | systemd-stub(7) هرگونه ایمیج systemd-sysext(8) را که به کرنل بوتشده تحویل میدهد در این PCR اندازه میگیرد. |
| 14 | shim-policy | پروژه shim گواهیهای "MOK" و هشهای خود را در این PCR اندازهگیری میکند. |
| 15 | system-identity | systemd-cryptsetup(8) بهصورت اختیاری کلید حجم پارتیشنهای LUKS فعالشده را در این PCR اندازه میگیرد. systemd-pcrmachine.service(8) شناسه machine-id(5) را در این PCR اندازهگیری میکند. systemd-pcrfs@.service(8) نقاط اتصال، UUIDهای سیستمفایل، برچسبها و UUIDهای پارتیشن سیستمفایلهای ریشه و /var/ را در این PCR اندازهگیری مینماید. |
| 16 | debug | اشکالزدایی (Debug) |
| 23 | application-support | پشتیبانی از برنامهها (Application Support) |
بهطور
کلی،
حجمهای
رمزگذاریشده
به ترکیبی
از PCRهای 7، 11 و 14
(در صورت
استفاده از
shim/MOK) مقید
میشوند. به
منظور
امکانپذیر
ساختن
بهروزرسانیهای
میانافزار
و
نگارشهای
سیستمعامل،
معمولاً
استفاده از
PCRهایی مانند
0 و 2 توصیه
نمیشود،
زیرا کد
برنامهای
که آنها
پوشش
میدهند
قبلاً
بهطور
غیرمستقیم
از طریق
گواهیهای
اندازهگیریشده
در PCR 7 پوشش
داده شده
است.
اعتبارسنجی
از طریق هش
گواهیها
معمولاً
نسبت به
اعتبارسنجی
از طریق
اندازهگیریهای
مستقیم
ارجحیت
دارد زیرا
در شرایط
بهروزرسانی
سیستمعامل/میانافزار
شکنندهتر
نیست:
اندازهگیریها
در هر
بهروزرسانی
تغییر
میکنند،
اما امضاها
بدون تغییر
باقی
میمانند.
برای
توضیحات و
بررسی
بیشتر به
UAPI.7 Linux TPM PCR Registry[1]
مراجعه
فرمایید.
محدودیتها (LIMITATIONS)
توجه داشته باشید که در حال حاضر هنگام ثبت یک کلید جدید از یکی از پنج نوع پشتیبانیشده ذکرشده در بالا، ابتدا باید یک عبارت عبور، یک کلید بازیابی، یک توکن FIDO2، یا یک کلید TPM2 ارائه دهید. در حال حاضر باز کردن قفل دستگاه با کلید PKCS#11 به منظور ثبت یک کلید جدید PKCS#11 پشتیبانی نمیشود. بنابراین، اگر در آینده چرخش کلید (key roll-over) مد نظر باشد، معمولاً توصیه میشود اطمینان حاصل کنید که همواره یک عبارت عبور، یک کلید بازیابی، یک توکن FIDO2، یا یک کلید TPM2 ثبت شده باشد.
همچنین توجه داشته باشید که پشتیبانی از ثبت چندین توکن FIDO2 در حال حاضر محدود است. هنگامی که چندین توکن FIDO2 ثبت شده باشند، systemd-cryptsetup درخواستهای پیشپروازی (pre-flight) را برای شناسایی توکنهایی از میان توکنهای ثبتشده که هماکنون به سیستم متصل هستند ارسال میکند. با این حال، این کار برای توکنهای FIDO2 دارای تأیید هویت کاربر (UV، معمولاً از طریق زیستسنجی/بیومتریک) امکانپذیر نیست، که در این صورت تلاش برای هر یک از توکنهای ثبتشده را یکی پس از دیگری انجام میدهد. این امر منجر به نمایش چندین اعلان برای دریافت PIN و تأیید هویت کاربر خواهد شد. این محدودیت در مورد توکنهای PKCS#11 اعمال نمیشود.
سازگاری (COMPATIBILITY)
فناوریهای امنیتی هم در systemd و هم در کل صنعت پیوسته در حال تحول هستند. به منظور ارائه بهترین تضمینهای امنیتی، شیوه ثبت دستگاههای TPM2، FIDO2 و PKCS#11 مرتباً در نسخههای جدیدتر systemd بهروزرسانی میشود. هر زمان که این اتفاق بیفتد، تضمینهای سازگاری زیر ارائه میشوند:
با این اوصاف، معمولاً توصیه میشود از نسخههای منطبق systemd-cryptenroll و systemd-cryptsetup استفاده کنید، چرا که این ترکیب به بهترین نحو آزمایش شده و پشتیبانی میشود.
همچنین ممکن است بهمنظور بهرهمندی از ویژگیهای امنیتی جدیدتر که به systemd اضافه میشوند، ثبت مجدد موارد موجود توصیه شود.
گزینهها (OPTIONS)
قفلگشایی (UNLOCKING)
گزینههای زیر برای باز کردن قفل دستگاه جهت آمادهسازی عملیات ثبت پشتیبانی میشوند:
--unlock-key-file=PATH
افزودهشده در نسخه 252.
--unlock-fido2-device=PATH
افزودهشده در نسخه 253.
--unlock-tpm2-device=PATH
افزودهشده در نسخه 256.
ثبت ساده (SIMPLE ENROLLMENT)
گزینههای زیر برای ثبت قفلگشایی مبتنی بر ورودی ساده کاربر پشتیبانی میشوند:
--password
افزودهشده در نسخه 248.
--recovery-key
افزودهشده در نسخه 248.
ثبت PKCS#11 (PKCS#11 ENROLLMENT)
گزینه زیر برای ثبت توکنهای PKCS#11 پشتیبانی میشود:
--pkcs11-token-uri=URI
توکن PKCS#11 باید حاوی یک جفتکلید RSA یا EC باشد که برای باز کردن قفل حجم LUKS2 استفاده خواهد شد. برای RSA، یک کلید حجم که بهطور تصادفی تولید شده با کلید عمومی موجود در توکن رمزگذاری شده و در ناحیه هدر توکن JSON در LUKS2 ذخیره میشود. برای باز کردن قفل حجم، کلید حجم رمزگذاریشده ذخیرهشده با کلید خصوصی درون توکن رمزگشایی خواهد شد. برای ECC، از الگوریتم ECDH استفاده میشود: ما یک جفتکلید EC در همان گروه EC تولید میکنیم، سپس با استفاده از کلید خصوصی تولیدشده و کلید عمومی موجود در توکن، یک راز مشترک (shared secret) استخراج مینماییم. راز مشترک استخراجشده به عنوان کلید حجم استفاده میشود. کلید عمومی تولیدشده در ناحیه هدر توکن JSON در LUKS2 ذخیره میشود. کلید خصوصی تولیدشده پاک میگردد. برای باز کردن قفل حجم، راز مشترک با استفاده از کلید عمومی ذخیرهشده و یک کلید خصوصی درون توکن مشتق میشود.
به منظور باز کردن قفل حجم LUKS2 با یک توکن امنیتی ثبتشده PKCS#11، گزینه pkcs11-uri= را در سطر مربوطه در /etc/crypttab مشخص کنید:
myvolume /dev/sda1 none pkcs11-uri=auto
برای مثالی جامعتر از فراخوانی systemd-cryptenroll و خط منطبق آن در /etc/crypttab به crypttab(5) مراجعه فرمایید.
افزودهشده در نسخه 248.
ثبت FIDO2 (FIDO2 ENROLLMENT)
گزینههای زیر برای ثبت توکنهای FIDO2 پشتیبانی میشوند:
--fido2-device=PATH
برای باز کردن قفل یک حجم LUKS2 با یک توکن امنیتی ثبتشده FIDO2، گزینه fido2-device= را در خط مربوطه در /etc/crypttab تعیین کنید:
myvolume /dev/sda1 none fido2-device=auto
برای مثالی جامعتر از فراخوانی systemd-cryptenroll و خط متناظر آن در /etc/crypttab به crypttab(5) مراجعه کنید.
افزودهشده در نسخه 248.
--fido2-credential-algorithm=STRING
"es256" بیانگر ECDSA روی NIST P-256 همراه با SHA-256 است. "rs256" بیانگر RSA با کلید ۲۰۴۸ بیتی همراه با پدینگ PKCS#1.5 و SHA-256 است. "eddsa" بیانگر EDDSA روی Curve25519 همراه با SHA-512 است.
توجه داشته باشید احرازکنندهکننده (authenticator) شما ممکن است از برخی از این الگوریتمها پشتیبانی نکند.
افزودهشده در نسخه 251.
--fido2-salt-file=PATH
افزودهشده در نسخه 257.
--fido2-parameters-in-header=BOOL
افزودهشده در نسخه 257.
--fido2-with-client-pin=BOOL
افزودهشده در نسخه 249.
--fido2-with-user-presence=BOOL
افزودهشده در نسخه 249.
--fido2-with-user-verification=BOOL
افزودهشده در نسخه 249.
ثبت TPM2 (TPM2 ENROLLMENT)
گزینههای زیر برای ثبت دستگاههای TPM2 پشتیبانی میشوند:
--tpm2-device=PATH
برای باز کردن قفل یک حجم LUKS2 با یک تراشه امنیتی ثبتشده TPM2، گزینه tpm2-device= را در سطر متناظر در /etc/crypttab مشخص کنید:
myvolume /dev/sda1 none tpm2-device=auto
برای مثالی جامعتر از فراخوانی systemd-cryptenroll و خط منطبق آن در /etc/crypttab به crypttab(5) مراجعه نمایید.
از گزینه --tpm2-pcrs= (در ادامه را ببینید) برای پیکربندی این که ثبت به کدام شاخصهای PCR در TPM2 مقید شود استفاده کنید.
افزودهشده در نسخه 248.
--tpm2-device-key=PATH
این کلید در اغلب موارد باید کلید ریشه ذخیرهسازی (Storage Root Key یا SRK) از یک تراشه محلی امنیتی TPM2 باشد. اگر کلیدی از یک هندل دیگر (غیر از SRK) استفاده شود، باید شاخص هندل آن را با استفاده از --tpm2-seal-key-handle= مشخص کنید.
سرویس systemd-tpm2-setup.service(8) کلید SRK را در طول بوت بهطور خودکار در قالب صحیح در مسیر /run/systemd/tpm2-srk-public-key.tpm2b_public مینویسد.
متناوباً، میتوانید از دستور systemd-analyze srk برای دریافت صریح SRK از تراشه امنیتی TPM2 استفاده کنید. برای جزئیات به systemd-analyze(1) مراجعه کنید. مثال:
systemd-analyze srk > srk.tpm2b_public
افزودهشده در نسخه 255.
--tpm2-seal-key-handle=HANDLE
مقدار پیشفرض، شاخص هندل کلید ریشه ذخیرهسازی (SRK) یعنی "0x81000001" است. مقدار 0 از پیشفرض استفاده میکند. برای هندل SRK، اگر کلیدی از قبل وجود نداشته باشد، کلید جدیدی در TPM ایجاد و ذخیره میشود؛ برای هر هندل دیگری، کلید باید قبلاً در شاخص هندل مشخصشده در TPM وجود داشته باشد.
این گزینه نباید تغییر کند مگر اینکه دقیقاً بدانید چه کار میکنید.
افزودهشده در نسخه 255.
--tpm2-pcrs=PCR[+PCR...]
مثال: --tpm2-pcrs=boot-loader-code+platform-config+boot-loader-config مشخص میکند که ثباتهای PCR شماره 4، 1 و 5 باید استفاده شوند.
مثال: --tpm2-pcrs=7:sha256 مشخص میکند که ثبات PCR شماره 7 از بانک SHA256 باید استفاده شود.
مثال: --tpm2-pcrs=4:sha1=3a3f780f11a4b49969fcaa80cd6e3957c33b2275 مشخص میکند که ثبات PCR شماره 4 از بانک SHA1 باید استفاده شود، و مقدار دایجست هش 3a3f780f11a4b49969fcaa80cd6e3957c33b2275 به جای خواندن مقدار فعلی PCR استفاده خواهد شد.
افزودهشده در نسخه 248.
--tpm2-with-pin=BOOL
توجه داشته باشید که ورود اشتباه PIN در حین قفلگشایی، شمارنده سازوکار قفلشدگی در برابر حمله فرهنگلغت (dictionary attack lockout) در TPM را افزایش میدهد، و بسته به پیکربندی آن ممکن است کاربران را برای مدت طولانی از دسترسی محروم کند. سازوکار قفلشدگی یک ویژگی سراسری در TPM است؛ systemd-cryptenroll سازوکار قفلشدگی را کنترل یا پیکربندی نمیکند. میتوانید برای بررسی یا پیکربندی قفل حمله فرهنگلغت، بهترتیب از دستورات tpm2_getcap(1) و tpm2_dictionarylockout(1) از ابزارهای tpm2-tss استفاده کنید.
افزودهشده در نسخه 251.
--tpm2-public-key=PATH، --tpm2-public-key-pcrs=PCR[+PCR...]، --tpm2-signature=PATH
به تفاوت میان --tpm2-pcrs= و --tpm2-public-key-pcrs= توجه کنید: اولی رمزگشایی را به مقادیر فعلی و مشخص PCR مقید میکند؛ دومی رمزگشایی را به هر مجموعهای از مقادیر PCR که بتوان امضایی از طریق کلید عمومی مشخصشده برای آن ارائه داد مقید میسازد. بنابراین گزینه دوم در سناریوهایی که باید امکان بهروزرسانی نرمافزار بدون از دست رفتن دسترسی به تمام حجمهای رمزگذاریشده قبلی LUKS2 وجود داشته باشد، مفیدتر است. همانند --tpm2-pcrs=، میتوان از نامهای تعریفشده در جدول بالا نیز برای تعیین ثباتها استفاده کرد، برای مثال --tpm2-public-key-pcrs=boot-loader-code+system-identity.
گزینه --tpm2-signature= مسیری به یک فایل امضای PCR در TPM2 را که توسط ابزار systemd-measure(1) تولید شده است میپذیرد. اگر این مورد بهصورت صریح تعیین نشود، یک فایل امضای مناسب با نام tpm2-pcr-signature.json به ترتیب در /etc/systemd/، /run/systemd/ و /usr/lib/systemd/ جستجو شده و استفاده میگردد. اگر فایل امضا مشخص شود یا یافت گردد، قبل از این که اسلات جدید روی دیسک نوشته شود، برای اعتبارسنجی این که آیا حجم با توجه به وضعیت فعلی PCR قابل بازگشایی است یا خیر استفاده میشود. این عمل به عنوان یک تور ایمنی عمل میکند تا اطمینان حاصل شود که اگر کلید عمومی ثبت شود که هیچ امضای معتبری برای وضعیت فعلی PCR برای آن وجود ندارد، دسترسی به حجم از بین نرود. اگر امضای ارائهشده ترکیب وضعیت فعلی PCR و کلید عمومی را بازگشایی نکند، هیچ اسلاتی ثبت نمیشود و عملیات با شکست مواجه خواهد شد. اگر هیچ فایل امضایی مشخص یا پیدا نشود، چنین اعتبارسنجی ایمنی انجام نمیگیرد.
افزودهشده در نسخه 252.
--tpm2-pcrlock=PATH
افزودهشده در نسخه 255.
سایر گزینهها (OTHER OPTIONS)
گزینههای تکمیلی زیر پشتیبانی میشوند:
--wipe-slot=SLOT[,SLOT...]
این سوییچ میتواند به تنهایی استفاده شود که در این حالت فقط عملیات پاکسازی درخواستی اجرا میگردد. همچنین میتواند با هر یک از گزینههای ثبت ذکرشده در بالا ترکیب شود، که در این حالت ابتدا ثبت تکمیل میشود و تنها در صورت موفقیت، عملیات پاکسازی انجام میگیرد — و اسلات تازهافزوده همیشه از پاکسازی مستثنی میشود. بنابراین ترکیب ثبت و پاکسازی اسلات میتواند برای بهروزرسانی ثبتهای موجود استفاده شود:
systemd-cryptenroll /dev/sda1 --wipe-slot=tpm2 --tpm2-device=auto --unlock-tpm2-device=auto
دستور بالا تراشه TPM2 را ثبت میکند، و سپس تمام ثبتهای TPM2 قبلی روی حجم LUKS2 را پاک کرده و تنها ثبت جدیداً ایجادشده را باقی میگذارد. ترکیب پاکسازی و ثبت همچنین میتواند برای جایگزینی ثبتهایی از انواع مختلف استفاده شود، برای نمونه تغییر از ثبت PKCS#11 به FIDO2:
systemd-cryptenroll /dev/sda1 --wipe-slot=pkcs11 --fido2-device=auto
یا برای جایگزینی رمز عبور خالی ثبتشده با TPM2:
systemd-cryptenroll /dev/sda1 --wipe-slot=empty --tpm2-device=auto
افزودهشده در نسخه 248.
--list-devices
افزودهشده در نسخه 257.
-h، --help
--version
--no-pager
اعتبارنامهها (CREDENTIALS)
systemd-cryptenroll از منطق اعتبارنامههای سرویس همانطور که توسط ImportCredential=/LoadCredential=/SetCredential= پیادهسازی شده است پشتیبانی میکند (برای جزئیات به systemd.exec(5) مراجعه کنید). اعتبارنامههای زیر در صورت ارسال استفاده میشوند:
cryptenroll.passphrase، cryptenroll.new-passphrase
افزودهشده در نسخه 256.
cryptenroll.tpm2-pin، cryptenroll.new-tpm2-pin
افزودهشده در نسخه 256.
cryptenroll.fido2-pin
افزودهشده در نسخه 256.
cryptenroll.pkcs11-pin
افزودهشده در نسخه 256.
کدهای خروج (EXIT STATUS)
در صورت موفقیت 0 بازگردانده میشود، و در غیر این صورت یک کد خطای غیرصفر بازگردانده خواهد شد.
مثالها (EXAMPLES)
صفحات راهنمای crypttab(5) و systemd-measure(1) شامل مثالهای مختلفی هستند که در آنها از systemd-cryptenroll استفاده شده است.
همچنین ببینید (SEE ALSO)
systemd(1)، systemd-cryptsetup@.service(8)، crypttab(5)، cryptsetup(8)، systemd-measure(1)
یادداشتها (NOTES)
- 1.
- UAPI.7 Linux TPM PCR Registry
| systemd 261.2 |