--- a/arch/mips/include/asm/r4kcache.h +++ b/arch/mips/include/asm/r4kcache.h @@ -28,6 +28,38 @@ extern void (*r4k_blast_dcache)(void); extern void (*r4k_blast_icache)(void); +#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) +#include +#include +#define BCM4710_DUMMY_RREG() bcm4710_dummy_rreg() + +static inline unsigned long bcm4710_dummy_rreg(void) +{ + return *(volatile unsigned long *)(KSEG1ADDR(SSB_ENUM_BASE)); +} + +#define BCM4710_FILL_TLB(addr) bcm4710_fill_tlb((void *)(addr)) + +static inline unsigned long bcm4710_fill_tlb(void *addr) +{ + return *(unsigned long *)addr; +} + +#define BCM4710_PROTECTED_FILL_TLB(addr) bcm4710_protected_fill_tlb((void *)(addr)) + +static inline void bcm4710_protected_fill_tlb(void *addr) +{ + unsigned long x; + get_dbe(x, (unsigned long *)addr);; +} + +#else +#define BCM4710_DUMMY_RREG() + +#define BCM4710_FILL_TLB(addr) +#define BCM4710_PROTECTED_FILL_TLB(addr) +#endif + /* * This macro return a properly sign-extended address suitable as base address * for indexed cache operations. Two issues here: @@ -61,6 +93,7 @@ static inline void flush_icache_line_ind static inline void flush_dcache_line_indexed(unsigned long addr) { + BCM4710_DUMMY_RREG(); cache_op(Index_Writeback_Inv_D, addr); } @@ -84,11 +117,13 @@ static inline void flush_icache_line(uns static inline void flush_dcache_line(unsigned long addr) { + BCM4710_DUMMY_RREG(); cache_op(Hit_Writeback_Inv_D, addr); } static inline void invalidate_dcache_line(unsigned long addr) { + BCM4710_DUMMY_RREG(); cache_op(Hit_Invalidate_D, addr); } @@ -161,6 +196,7 @@ static inline int protected_flush_icache #ifdef CONFIG_EVA return protected_cachee_op(Hit_Invalidate_I, addr); #else + BCM4710_DUMMY_RREG(); return protected_cache_op(Hit_Invalidate_I, addr); #endif } @@ -174,6 +210,7 @@ static inline int protected_flush_icache */ static inline int protected_writeback_dcache_line(unsigned long addr) { + BCM4710_DUMMY_RREG(); #ifdef CONFIG_EVA return protected_cachee_op(Hit_Writeback_Inv_D, addr); #else @@ -203,8 +240,51 @@ static inline void invalidate_tcache_pag unroll(times, _cache_op, insn, op, (addr) + (i++ * (lsize))); \ } while (0) +static inline void blast_dcache(void) +{ + unsigned long start = KSEG0; + unsigned long dcache_size = current_cpu_data.dcache.waysize * current_cpu_data.dcache.ways; + unsigned long end = (start + dcache_size); + + do { + BCM4710_DUMMY_RREG(); + cache_op(Index_Writeback_Inv_D, start); + start += current_cpu_data.dcache.linesz; + } while(start < end); +} + +static inline void blast_dcache_page(unsigned long page) +{ + unsigned long start = page; + unsigned long end = start + PAGE_SIZE; + + BCM4710_FILL_TLB(start); + do { + BCM4710_DUMMY_RREG(); + cache_op(Hit_Writeback_Inv_D, start); + start += current_cpu_data.dcache.linesz; + } while(start < end); +} + +static inline void blast_dcache_page_indexed(unsigned long page) +{ + unsigned long start = page; + unsigned long end = start + PAGE_SIZE; + unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit; + unsigned long ws_end = current_cpu_data.dcache.ways << + current_cpu_data.dcache.waybit; + unsigned long ws, addr; + for (ws = 0; ws < ws_end; ws += ws_inc) { + start = page + ws; + for (addr = start; addr < end; addr += current_cpu_data.dcache.linesz) { + BCM4710_DUMMY_RREG(); + cache_op(Index_Writeback_Inv_D, addr); + } + } +} + /* build blast_xxx, blast_xxx_page, blast_xxx_page_indexed */ -#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra) \ +#define __BUILD_BLAST_CACHE(pfx, desc, indexop, hitop, lsize, extra, war) \ static inline void extra##blast_##pfx##cache##lsize(void) \ { \ unsigned long start = INDEX_BASE; \ @@ -214,6 +294,7 @@ static inline void extra##blast_##pfx##c current_cpu_data.desc.waybit; \ unsigned long ws, addr; \ \ + war \ for (ws = 0; ws < ws_end; ws += ws_inc) \ for (addr = start; addr < end; addr += lsize * 32) \ cache_unroll(32, kernel_cache, indexop, \ @@ -225,6 +306,7 @@ static inline void extra##blast_##pfx##c unsigned long start = page; \ unsigned long end = page + PAGE_SIZE; \ \ + war \ do { \ cache_unroll(32, kernel_cache, hitop, start, lsize); \ start += lsize * 32; \ @@ -241,32 +323,33 @@ static inline void extra##blast_##pfx##c current_cpu_data.desc.waybit; \ unsigned long ws, addr; \ \ + war \ for (ws = 0; ws < ws_end; ws += ws_inc) \ for (addr = start; addr < end; addr += lsize * 32) \ cache_unroll(32, kernel_cache, indexop, \ addr | ws, lsize); \ } -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, ) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, ) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, ) -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, ) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, ) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, ) -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, ) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, ) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, ) -__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, ) -__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, ) -__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, ) - -__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, ) -__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, ) -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, ) -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, ) -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, ) -__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, ) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16, , ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16, , BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16, , ) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32, , ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32, , BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I_Loongson2, 32, loongson2_, BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32, , ) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64, , ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64, , BCM4710_FILL_TLB(start);) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64, , ) +__BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 128, , ) +__BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 128, , ) +__BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128, , ) + +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16, , ) +__BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32, , ) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16, , ) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32, , ) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64, , ) +__BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128, , ) #define __BUILD_BLAST_USER_CACHE(pfx, desc, indexop, hitop, lsize) \ static inline void blast_##pfx##cache##lsize##_user_page(unsigned long page) \ @@ -291,58 +374,29 @@ __BUILD_BLAST_USER_CACHE(d, dcache, Inde __BUILD_BLAST_USER_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64) /* build blast_xxx_range, protected_blast_xxx_range */ -#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra) \ +#define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot, extra, war, war2) \ static inline void prot##extra##blast_##pfx##cache##_range(unsigned long start, \ unsigned long end) \ { \ unsigned long lsize = cpu_##desc##_line_size(); \ - unsigned long lsize_2 = lsize * 2; \ - unsigned long lsize_3 = lsize * 3; \ - unsigned long lsize_4 = lsize * 4; \ - unsigned long lsize_5 = lsize * 5; \ - unsigned long lsize_6 = lsize * 6; \ - unsigned long lsize_7 = lsize * 7; \ - unsigned long lsize_8 = lsize * 8; \ unsigned long addr = start & ~(lsize - 1); \ - unsigned long aend = (end + lsize - 1) & ~(lsize - 1); \ - int lines = (aend - addr) / lsize; \ - \ - while (lines >= 8) { \ - prot##cache_op(hitop, addr); \ - prot##cache_op(hitop, addr + lsize); \ - prot##cache_op(hitop, addr + lsize_2); \ - prot##cache_op(hitop, addr + lsize_3); \ - prot##cache_op(hitop, addr + lsize_4); \ - prot##cache_op(hitop, addr + lsize_5); \ - prot##cache_op(hitop, addr + lsize_6); \ - prot##cache_op(hitop, addr + lsize_7); \ - addr += lsize_8; \ - lines -= 8; \ - } \ - \ - if (lines & 0x4) { \ - prot##cache_op(hitop, addr); \ - prot##cache_op(hitop, addr + lsize); \ - prot##cache_op(hitop, addr + lsize_2); \ - prot##cache_op(hitop, addr + lsize_3); \ - addr += lsize_4; \ - } \ + unsigned long aend = (end - 1) & ~(lsize - 1); \ \ - if (lines & 0x2) { \ - prot##cache_op(hitop, addr); \ - prot##cache_op(hitop, addr + lsize); \ - addr += lsize_2; \ - } \ + war \ \ - if (lines & 0x1) { \ + while (1) { \ + war2 \ prot##cache_op(hitop, addr); \ + if (addr == aend) \ + break; \ + addr += lsize; \ } \ } #ifndef CONFIG_EVA -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, ) -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, ) +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_, , BCM4710_PROTECTED_FILL_TLB(addr); BCM4710_PROTECTED_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_, , , ) #else @@ -376,15 +430,15 @@ __BUILD_PROT_BLAST_CACHE_RANGE(d, dcache __BUILD_PROT_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I) #endif -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, ) +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_, , , ) __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I_Loongson2, \ - protected_, loongson2_) -__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , ) -__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , ) -__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , ) + protected_, loongson2_, , ) +__BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, , , BCM4710_FILL_TLB(addr); BCM4710_FILL_TLB(aend);, BCM4710_DUMMY_RREG();) +__BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, , , , ) +__BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, , , , ) /* blast_inv_dcache_range */ -__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , ) -__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , ) +__BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, , , , BCM4710_DUMMY_RREG();) +__BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, , , , ) /* Currently, this is very specific to Loongson-3 */ #define __BUILD_BLAST_CACHE_NODE(pfx, desc, indexop, hitop, lsize) \ --- a/arch/mips/include/asm/stackframe.h +++ b/arch/mips/include/asm/stackframe.h @@ -429,6 +429,10 @@ #else .set push .set arch=r4000 +#ifdef CONFIG_BCM47XX + nop + nop +#endif eret .set pop #endif --- a/arch/mips/kernel/genex.S +++ b/arch/mips/kernel/genex.S @@ -22,6 +22,19 @@ #include #include +#ifdef CONFIG_BCM47XX +# ifdef eret +# undef eret +# endif +# define eret \ + .set push; \ + .set noreorder; \ + nop; \ + nop; \ + eret; \ + .set pop; +#endif + __INIT /* @@ -33,6 +46,9 @@ NESTED(except_vec3_generic, 0, sp) .set push .set noat +#ifdef CONFIG_BCM47XX + nop +#endif mfc0 k1, CP0_CAUSE andi k1, k1, 0x7c #ifdef CONFIG_64BIT @@ -53,6 +69,9 @@ NESTED(except_vec3_r4000, 0, sp) .set push .set arch=r4000 .set noat +#ifdef CONFIG_BCM47XX + nop +#endif mfc0 k1, CP0_CAUSE li k0, 31<<2 andi k1, k1, 0x7c --- a/arch/mips/mm/c-r4k.c +++ b/arch/mips/mm/c-r4k.c @@ -38,6 +38,9 @@ #include #include +/* For enabling BCM4710 cache workarounds */ +static int bcm4710 = 0; + /* * Bits describing what cache ops an SMP callback function may perform. * @@ -190,6 +193,9 @@ static void r4k_blast_dcache_user_page_s { unsigned long dc_lsize = cpu_dcache_line_size(); + if (bcm4710) + r4k_blast_dcache_page = blast_dcache_page; + else if (dc_lsize == 0) r4k_blast_dcache_user_page = (void *)cache_noop; else if (dc_lsize == 16) @@ -208,6 +214,9 @@ static void r4k_blast_dcache_page_indexe { unsigned long dc_lsize = cpu_dcache_line_size(); + if (bcm4710) + r4k_blast_dcache_page_indexed = blast_dcache_page_indexed; + else if (dc_lsize == 0) r4k_blast_dcache_page_indexed = (void *)cache_noop; else if (dc_lsize == 16) @@ -227,6 +236,9 @@ static void r4k_blast_dcache_setup(void) { unsigned long dc_lsize = cpu_dcache_line_size(); + if (bcm4710) + r4k_blast_dcache = blast_dcache; + else if (dc_lsize == 0) r4k_blast_dcache = (void *)cache_noop; else if (dc_lsize == 16) @@ -1818,6 +1830,17 @@ static void coherency_setup(void) * silly idea of putting something else there ... */ switch (current_cpu_type()) { + case CPU_BMIPS3300: + { + u32 cm; + cm = read_c0_diag(); + /* Enable icache */ + cm |= (1 << 31); + /* Enable dcache */ + cm |= (1 << 30); + write_c0_diag(cm); + } + break; case CPU_R4000PC: case CPU_R4000SC: case CPU_R4000MC: @@ -1864,6 +1887,15 @@ void r4k_cache_init(void) extern void build_copy_page(void); struct cpuinfo_mips *c = ¤t_cpu_data; + /* Check if special workarounds are required */ +#if defined(CONFIG_BCM47XX) && !defined(CONFIG_CPU_MIPS32_R2) + if (current_cpu_data.cputype == CPU_BMIPS32 && (current_cpu_data.processor_id & 0xff) == 0) { + printk("Enabling BCM4710A0 cache workarounds.\n"); + bcm4710 = 1; + } else +#endif + bcm4710 = 0; + probe_pcache(); probe_vcache(); setup_scache(); @@ -1940,7 +1972,15 @@ void r4k_cache_init(void) */ local_r4k___flush_cache_all(NULL); +#ifdef CONFIG_BCM47XX + { + static void (*_coherency_setup)(void); + _coherency_setup = (void (*)(void)) KSEG1ADDR(coherency_setup); + _coherency_setup(); + } +#else coherency_setup(); +#endif board_cache_error_setup = r4k_cache_error_setup; /* --- a/arch/mips/mm/tlbex.c +++ b/arch/mips/mm/tlbex.c @@ -984,6 +984,9 @@ void build_get_pgde32(u32 **p, unsigned uasm_i_srl(p, ptr, ptr, SMP_CPUID_PTRSHIFT); uasm_i_addu(p, ptr, tmp, ptr); #else +#ifdef CONFIG_BCM47XX + uasm_i_nop(p); +#endif UASM_i_LA_mostly(p, ptr, pgdc); #endif uasm_i_mfc0(p, tmp, C0_BADVADDR); /* get faulting address */ @@ -1345,6 +1348,9 @@ static void build_r4000_tlb_refill_handl #ifdef CONFIG_64BIT build_get_pmde64(&p, &l, &r, K0, K1); /* get pmd in K1 */ #else +# ifdef CONFIG_BCM47XX + uasm_i_nop(&p); +# endif build_get_pgde32(&p, K0, K1); /* get pgd in K1 */ #endif @@ -1356,6 +1362,9 @@ static void build_r4000_tlb_refill_handl build_update_entries(&p, K0, K1); build_tlb_write_entry(&p, &l, &r, tlb_random); uasm_l_leave(&l, p); +#ifdef CONFIG_BCM47XX + uasm_i_nop(&p); +#endif uasm_i_eret(&p); /* return from trap */ } #ifdef CONFIG_MIPS_HUGE_TLB_SUPPORT @@ -2056,6 +2065,9 @@ build_r4000_tlbchange_handler_head(u32 * #ifdef CONFIG_64BIT build_get_pmde64(p, l, r, wr.r1, wr.r2); /* get pmd in ptr */ #else +# ifdef CONFIG_BCM47XX + uasm_i_nop(p); +# endif build_get_pgde32(p, wr.r1, wr.r2); /* get pgd in ptr */ #endif @@ -2102,6 +2114,9 @@ build_r4000_tlbchange_handler_tail(u32 * build_tlb_write_entry(p, l, r, tlb_indexed); uasm_l_leave(l, *p); build_restore_work_registers(p); +#ifdef CONFIG_BCM47XX + uasm_i_nop(p); +#endif uasm_i_eret(p); /* return from trap */ #ifdef CONFIG_64BIT 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627
.. hazmat::

Interfaces
==========


``cryptography`` uses `Abstract Base Classes`_ as interfaces to describe the
properties and methods of most primitive constructs. Backends may also use
this information to influence their operation. Interfaces should also be used
to document argument and return types.

.. _`Abstract Base Classes`: http://docs.python.org/3.2/library/abc.html


Symmetric ciphers
-----------------

.. currentmodule:: cryptography.hazmat.primitives.interfaces


.. class:: CipherAlgorithm

    A named symmetric encryption algorithm.

    .. attribute:: name

        :type: str

        The standard name for the mode, for example, "AES", "Camellia", or
        "Blowfish".

    .. attribute:: key_size

        :type: int

        The number of bits in the key being used.


.. class:: BlockCipherAlgorithm

    A block cipher algorithm.

    .. attribute:: block_size

        :type: int

        The number of bits in a block.


Cipher modes
~~~~~~~~~~~~

Interfaces used by the symmetric cipher modes described in
:ref:`Symmetric Encryption Modes <symmetric-encryption-modes>`.

.. class:: Mode

    A named cipher mode.

    .. attribute:: name

        :type: str

        This should be the standard shorthand name for the mode, for example
        Cipher-Block Chaining mode is "CBC".

        The name may be used by a backend to influence the operation of a
        cipher in conjunction with the algorithm's name.

    .. method:: validate_for_algorithm(algorithm)

        :param CipherAlgorithm algorithm:

        Checks that the combination of this mode with the provided algorithm
        meets any necessary invariants. This should raise an exception if they
        are not met.

        For example, the :class:`~cryptography.hazmat.primitives.modes.CBC`
        mode uses this method to check that the provided initialization
        vector's length matches the block size of the algorithm.


.. class:: ModeWithInitializationVector

    A cipher mode with an initialization vector.

    .. attribute:: initialization_vector

        :type: bytes

        Exact requirements of the initialization are described by the
        documentation of individual modes.


.. class:: ModeWithNonce

    A cipher mode with a nonce.

    .. attribute:: nonce

        :type: bytes

        Exact requirements of the nonce are described by the documentation of
        individual modes.

Asymmetric interfaces
---------------------

.. class:: AsymmetricSignatureContext

    .. versionadded:: 0.2

    .. method:: update(data)

        :param bytes data: The data you want to sign.

    .. method:: finalize()

        :return bytes signature: The signature.


.. class:: AsymmetricVerificationContext

    .. versionadded:: 0.2

    .. method:: update(data)

        :param bytes data: The data you wish to verify using the signature.

    .. method:: verify()

        :raises cryptography.exceptions.InvalidSignature: If the signature does
            not validate.


.. class:: AsymmetricPadding

    .. versionadded:: 0.2

    .. attribute:: name


RSA
~~~

.. class:: RSAPrivateKey

    .. versionadded:: 0.2

    An `RSA`_ private key.

    .. method:: signer(padding, algorithm)

        .. versionadded:: 0.3

        Sign data which can be verified later by others using the public key.

        :param padding: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
            provider.

        :param algorithm: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
            provider.

        :returns:
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`

    .. method:: decrypt(ciphertext, padding)

        .. versionadded:: 0.4

        Decrypt data that was encrypted via the public key.

        :param bytes ciphertext: The ciphertext to decrypt.

        :param padding: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
            provider.

        :return bytes: Decrypted data.

    .. method:: public_key()

        :return: :class:`~cryptography.hazmat.primitives.interfaces.RSAPublicKey`

        An RSA public key object corresponding to the values of the private key.

    .. attribute:: key_size

        :type: int

        The bit length of the modulus.

.. class:: RSAPrivateKeyWithNumbers

    .. versionadded:: 0.5

    Extends :class:`RSAPrivateKey`.

    .. method:: private_numbers()

        Create a
        :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
        object.

        :returns: An
            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPrivateNumbers`
            instance.


.. class:: RSAPublicKey

    .. versionadded:: 0.2

    An `RSA`_ public key.

    .. method:: verifier(signature, padding, algorithm)

        .. versionadded:: 0.3

        Verify data was signed by the private key associated with this public
        key.

        :param bytes signature: The signature to verify.

        :param padding: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
            provider.

        :param algorithm: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
            provider.

        :returns:
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`

    .. method:: encrypt(plaintext, padding)

        .. versionadded:: 0.4

        Encrypt data with the public key.

        :param bytes plaintext: The plaintext to encrypt.

        :param padding: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricPadding`
            provider.

        :return bytes: Encrypted data.

    .. attribute:: key_size

        :type: int

        The bit length of the modulus.


.. class:: RSAPublicKeyWithNumbers

    .. versionadded:: 0.5

    Extends :class:`RSAPublicKey`.

    .. method:: public_numbers()

        Create a
        :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
        object.

        :returns: An
            :class:`~cryptography.hazmat.primitives.asymmetric.rsa.RSAPublicNumbers`
            instance.


DSA
~~~

.. class:: DSAParameters

    .. versionadded:: 0.3

    `DSA`_ parameters.


.. class:: DSAParametersWithNumbers

    .. versionadded:: 0.5

    Extends :class:`DSAParameters`.

    .. method:: parameter_numbers()

        Create a
        :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`
        object.

        :returns: A
            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAParameterNumbers`
            instance.


.. class:: DSAPrivateKey

    .. versionadded:: 0.3

    A `DSA`_ private key.

    .. method:: public_key()

        :return: :class:`~cryptography.hazmat.primitives.interfaces.DSAPublicKey`

        An DSA public key object corresponding to the values of the private key.

    .. method:: parameters()

        :return: :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`

        The DSAParameters object associated with this private key.

    .. method:: signer(algorithm, backend)

        .. versionadded:: 0.4

        Sign data which can be verified later by others using the public key.

        :param algorithm: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
            provider.

        :param backend: A
            :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
            provider.

        :returns:
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricSignatureContext`

    .. attribute:: key_size

        :type: int

        The bit length of the modulus.


.. class:: DSAPrivateKeyWithNumbers

    .. versionadded:: 0.5

    Extends :class:`DSAPrivateKey`.

    .. method:: private_numbers()

        Create a
        :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
        object.

        :returns: A
            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPrivateNumbers`
            instance.


.. class:: DSAPublicKey

    .. versionadded:: 0.3

    A `DSA`_ public key.

    .. attribute:: key_size

        :type: int

        The bit length of the modulus.

    .. method:: parameters()

        :return: :class:`~cryptography.hazmat.primitives.interfaces.DSAParameters`

        The DSAParameters object associated with this public key.

    .. method:: verifier(signature, algorithm, backend)

        .. versionadded:: 0.4

        Verify data was signed by the private key associated with this public
        key.

        :param bytes signature: The signature to verify. DER encoded as
            specified in :rfc:`6979`.

        :param algorithm: An instance of a
            :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`
            provider.

        :param backend: A
            :class:`~cryptography.hazmat.backends.interfaces.DSABackend`
            provider.

        :returns:
            :class:`~cryptography.hazmat.primitives.interfaces.AsymmetricVerificationContext`


.. class:: DSAPublicKeyWithNumbers

    .. versionadded:: 0.5

    Extends :class:`DSAPublicKey`.

    .. method:: private_numbers()

        Create a
        :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
        object.

        :returns: A
            :class:`~cryptography.hazmat.primitives.asymmetric.dsa.DSAPublicNumbers`
            instance.


.. class:: EllipticCurve

    .. versionadded:: 0.5

    A named elliptic curve.

    .. attribute:: name

        :type: string

        The name of the curve. Usually the name used for the ASN.1 OID such as
        ``secp256k1``.

    .. attribute:: key_size

        :type: int

        The bit length of the curve's base point.


Elliptic Curve
~~~~~~~~~~~~~~

.. class:: EllipticCurveSignatureAlgorithm

    .. versionadded:: 0.5

    A signature algorithm for use with elliptic curve keys.

    .. attribute:: algorithm

        :type: :class:`~cryptography.hazmat.primitives.interfaces.HashAlgorithm`

        The digest algorithm to be used with the signature scheme.


.. class:: EllipticCurvePrivateKey

    .. versionadded:: 0.5

    An elliptic curve private key for use with an algorithm such as `ECDSA`_ or