├── .gitignore ├── .travis.yml ├── COPYING ├── MANIFEST.in ├── README.rst ├── appveyor.yml ├── blake2b_impl.c ├── blake2s_impl.c ├── doc_src ├── Makefile ├── conf.py ├── credits.rst ├── examples.rst ├── index.rst ├── installation.rst ├── module.rst ├── tree.odg └── tree.png ├── impl ├── blake2-config.h ├── blake2-impl.h ├── blake2.h ├── blake2b-load-sse2.h ├── blake2b-load-sse41.h ├── blake2b-ref.c ├── blake2b-round.h ├── blake2b.c ├── blake2s-load-sse2.h ├── blake2s-load-sse41.h ├── blake2s-load-xop.h ├── blake2s-ref.c ├── blake2s-round.h └── blake2s.c ├── pyblake2_impl_common.h ├── pyblake2module.c ├── setup.py ├── test ├── bench.py ├── test.py └── threads.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | MANIFEST 3 | build/* 4 | dist/* 5 | doc/* 6 | .tox/* 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | 3 | python: 4 | - "2.7" 5 | - "3.4" 6 | - "3.5" 7 | - "3.6" 8 | - pypy 9 | - pypy3 10 | 11 | install: 12 | - "pip install sphinx" 13 | 14 | script: 15 | - "python setup.py install" 16 | - "python test/test.py" 17 | - "cd doc_src" 18 | - "make doctest" 19 | 20 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Written in 2013 by Dmitry Chestnykh 2 | 3 | To the extent possible under law, the author have dedicated all copyright and 4 | related and neighboring rights to this software to the public domain worldwide. 5 | This software is distributed without any warranty. 6 | 7 | --- 8 | 9 | If a twisted mind of your lawyers or your jurisdiction doesn't recognize the 10 | right of the author to dedicate their copyrights, you can use one of the 11 | licenses listed below at your own choosing. (The condition in the preceeding 12 | sentence is not required for their use). 13 | 14 | --- 15 | 16 | PYBLAKE2 IS OCTUPLE-LICENSED UNDER THE FOLLOWING LICENSES 17 | (choose one or several at your own discretion): 18 | 19 | * CC0 Universal 1.0 - http://creativecommons.org/publicdomain/zero/1.0 20 | * Unlicense — http://unlicense.org/ 21 | * WTFPL Version 2 - http://www.wtfpl.net/ 22 | * Apache Public License 2.0 - https://www.apache.org/licenses/LICENSE-2.0 23 | * OpenSSL License - https://www.openssl.org/source/license.html 24 | * MIT License - https://opensource.org/licenses/MIT 25 | * The BSD 3-Clause License - https://opensource.org/licenses/BSD-3-Clause 26 | * ISC License - https://opensource.org/licenses/ISC 27 | 28 | --- 29 | 30 | This package includes code from the BLAKE2 project, which is only 31 | triple-licensed: "All code is triple-licensed under the CC0, the OpenSSL 32 | Licence, or the Apache Public License 2.0, at your choosing" and carries this notice: 33 | 34 | Copyright 2012, Samuel Neves . You may use this under the 35 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 36 | your option. The terms of these licenses can be found at: 37 | 38 | See https://github.com/BLAKE2/BLAKE2 39 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING 2 | include README.rst 3 | include MANIFEST.in 4 | include tox.ini 5 | include pyblake2_impl_common.h 6 | graft test 7 | graft impl 8 | graft doc_src 9 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | pyblake2 — BLAKE2 hash function for Python 2 | ========================================== 3 | 4 | Python 3.6 and later have native support for `BLAKE2 in hashlib `_ derived from this implementation, with compatible API. **Since all earlier Python versions reached end-of-life, this module is also EOL and will not be updated**. 5 | --------------------------------------- 6 | 7 | pyblake2 is an extension module for Python implementing BLAKE2 hash function. 8 | 9 | BLAKE2 is a cryptographic hash function, which offers highest security while 10 | being as fast as MD5 or SHA-1, and comes in two flavors: 11 | 12 | * BLAKE2b, optimized for 64-bit platforms and produces digests of any size 13 | between 1 and 64 bytes, 14 | 15 | * BLAKE2s, optimized for 8- to 32-bit platforms and produces digests of any 16 | size between 1 and 32 bytes. 17 | 18 | BLAKE2 supports keyed mode (a faster and simpler replacement for HMAC), 19 | salted hashing, personalization, and tree hashing. 20 | 21 | Hash objects from this module follow the API of standard library's 22 | `hashlib` objects. 23 | 24 | 25 | Installation 26 | ------------ 27 | 28 | From PyPI:: 29 | 30 | $ pip install pyblake2 31 | 32 | or download source code and run:: 33 | 34 | $ python setup.py install 35 | 36 | 37 | Usage 38 | ----- 39 | 40 | See documentation: http://pythonhosted.org/pyblake2/ 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | environment: 2 | matrix: 3 | 4 | # Pre-installed Python versions, which Appveyor may upgrade to 5 | # a later point release. 6 | 7 | - PYTHON: "C:\\Python27" 8 | PYTHON_VERSION: "2.7.x" 9 | PYTHON_ARCH: "32" 10 | 11 | - PYTHON: "C:\\Python27-x64" 12 | PYTHON_VERSION: "2.7.x" 13 | PYTHON_ARCH: "64" 14 | 15 | - PYTHON: "C:\\Python34" 16 | PYTHON_VERSION: "3.4.x" 17 | PYTHON_ARCH: "32" 18 | 19 | - PYTHON: "C:\\Python34-x64" 20 | PYTHON_VERSION: "3.4.x" 21 | PYTHON_ARCH: "64" 22 | 23 | - PYTHON: "C:\\Python35" 24 | PYTHON_VERSION: "3.5.x" 25 | PYTHON_ARCH: "32" 26 | 27 | - PYTHON: "C:\\Python35-x64" 28 | PYTHON_VERSION: "3.5.x" 29 | PYTHON_ARCH: "64" 30 | 31 | - PYTHON: "C:\\Python36" 32 | PYTHON_VERSION: "3.6.x" 33 | PYTHON_ARCH: "32" 34 | 35 | - PYTHON: "C:\\Python36-x64" 36 | PYTHON_VERSION: "3.6.x" 37 | PYTHON_ARCH: "64" 38 | 39 | init: 40 | - "ECHO Python %PYTHON_VERSION% (%PYTHON_ARCH%bit) from %PYTHON%" 41 | 42 | install: 43 | - ECHO "Filesystem root:" 44 | - ps: "ls \"C:/\"" 45 | 46 | - ECHO "Installed SDKs:" 47 | - ps: "ls \"C:/Program Files/Microsoft SDKs/Windows\"" 48 | 49 | # Update Python PATH of this build (so pip is available, this cannot be 50 | # done from inside the powershell script as it would require to restart 51 | # the parent CMD process). 52 | - "SET PATH=%PYTHON%;%PYTHON%\\Scripts;%PATH%" 53 | - "python --version" 54 | 55 | # Upgrade to the latest version of pip to avoid it displaying warnings 56 | # about it being out of date. 57 | - "pip install --disable-pip-version-check --user --upgrade pip" 58 | 59 | # Install twine, support for 'bdist_wheel' and update setuptools. 60 | - "pip install --upgrade wheel setuptools twine" 61 | 62 | build_script: 63 | - "python setup.py install" 64 | 65 | test_script: 66 | # Build the compiled extension and run the project tests 67 | - "python test/test.py" 68 | 69 | after_test: 70 | # If tests are successful, create binary packages for the project. 71 | - "python setup.py bdist_wheel" 72 | - ps: "ls dist" 73 | 74 | artifacts: 75 | # Archive the generated packages in the ci.appveyor.com build report. 76 | - path: dist\*.whl 77 | -------------------------------------------------------------------------------- /blake2b_impl.c: -------------------------------------------------------------------------------- 1 | #include "pyblake2_impl_common.h" 2 | 3 | #ifdef USE_OPTIMIZED_IMPL 4 | #include "impl/blake2b.c" 5 | #else 6 | #include "impl/blake2b-ref.c" 7 | #endif 8 | -------------------------------------------------------------------------------- /blake2s_impl.c: -------------------------------------------------------------------------------- 1 | #include "pyblake2_impl_common.h" 2 | 3 | #ifdef USE_OPTIMIZED_IMPL 4 | #include "impl/blake2s.c" 5 | #else 6 | #include "impl/blake2s-ref.c" 7 | #endif 8 | -------------------------------------------------------------------------------- /doc_src/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = ../doc 9 | 10 | # User-friendly check for sphinx-build 11 | ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) 12 | $(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) 13 | endif 14 | 15 | # Internal variables. 16 | PAPEROPT_a4 = -D latex_paper_size=a4 17 | PAPEROPT_letter = -D latex_paper_size=letter 18 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 19 | # the i18n builder cannot share the environment and doctrees with the others 20 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 21 | 22 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 23 | 24 | help: 25 | @echo "Please use \`make ' where is one of" 26 | @echo " html to make standalone HTML files" 27 | @echo " dirhtml to make HTML files named index.html in directories" 28 | @echo " singlehtml to make a single large HTML file" 29 | @echo " pickle to make pickle files" 30 | @echo " json to make JSON files" 31 | @echo " htmlhelp to make HTML files and a HTML help project" 32 | @echo " qthelp to make HTML files and a qthelp project" 33 | @echo " devhelp to make HTML files and a Devhelp project" 34 | @echo " epub to make an epub" 35 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 36 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 37 | @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" 38 | @echo " text to make text files" 39 | @echo " man to make manual pages" 40 | @echo " texinfo to make Texinfo files" 41 | @echo " info to make Texinfo files and run them through makeinfo" 42 | @echo " gettext to make PO message catalogs" 43 | @echo " changes to make an overview of all changed/added/deprecated items" 44 | @echo " xml to make Docutils-native XML files" 45 | @echo " pseudoxml to make pseudoxml-XML files for display purposes" 46 | @echo " linkcheck to check all external links for integrity" 47 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 48 | 49 | clean: 50 | rm -rf $(BUILDDIR)/* 51 | 52 | html: 53 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 54 | @echo 55 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 56 | 57 | dirhtml: 58 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 59 | @echo 60 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 61 | 62 | singlehtml: 63 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 64 | @echo 65 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 66 | 67 | pickle: 68 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 69 | @echo 70 | @echo "Build finished; now you can process the pickle files." 71 | 72 | json: 73 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 74 | @echo 75 | @echo "Build finished; now you can process the JSON files." 76 | 77 | htmlhelp: 78 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 79 | @echo 80 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 81 | ".hhp project file in $(BUILDDIR)/htmlhelp." 82 | 83 | qthelp: 84 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 85 | @echo 86 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 87 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 88 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pyblake2.qhcp" 89 | @echo "To view the help file:" 90 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pyblake2.qhc" 91 | 92 | devhelp: 93 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 94 | @echo 95 | @echo "Build finished." 96 | @echo "To view the help file:" 97 | @echo "# mkdir -p $$HOME/.local/share/devhelp/pyblake2" 98 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pyblake2" 99 | @echo "# devhelp" 100 | 101 | epub: 102 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 103 | @echo 104 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 105 | 106 | latex: 107 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 108 | @echo 109 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 110 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 111 | "(use \`make latexpdf' here to do that automatically)." 112 | 113 | latexpdf: 114 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 115 | @echo "Running LaTeX files through pdflatex..." 116 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 117 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 118 | 119 | latexpdfja: 120 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 121 | @echo "Running LaTeX files through platex and dvipdfmx..." 122 | $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja 123 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 124 | 125 | text: 126 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 127 | @echo 128 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 129 | 130 | man: 131 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 132 | @echo 133 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 134 | 135 | texinfo: 136 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 137 | @echo 138 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 139 | @echo "Run \`make' in that directory to run these through makeinfo" \ 140 | "(use \`make info' here to do that automatically)." 141 | 142 | info: 143 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 144 | @echo "Running Texinfo files through makeinfo..." 145 | make -C $(BUILDDIR)/texinfo info 146 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 147 | 148 | gettext: 149 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 150 | @echo 151 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 152 | 153 | changes: 154 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 155 | @echo 156 | @echo "The overview file is in $(BUILDDIR)/changes." 157 | 158 | linkcheck: 159 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 160 | @echo 161 | @echo "Link check complete; look for any errors in the above output " \ 162 | "or in $(BUILDDIR)/linkcheck/output.txt." 163 | 164 | doctest: 165 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 166 | @echo "Testing of doctests in the sources finished, look at the " \ 167 | "results in $(BUILDDIR)/doctest/output.txt." 168 | 169 | xml: 170 | $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml 171 | @echo 172 | @echo "Build finished. The XML files are in $(BUILDDIR)/xml." 173 | 174 | pseudoxml: 175 | $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml 176 | @echo 177 | @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." 178 | -------------------------------------------------------------------------------- /doc_src/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # pyblake2 documentation build configuration file, created by 4 | # sphinx-quickstart on Sun Apr 7 18:34:21 2013. 5 | # 6 | # This file is execfile()d with the current directory set to its containing dir. 7 | # 8 | # Note that not all possible configuration values are present in this 9 | # autogenerated file. 10 | # 11 | # All configuration values have a default; values that are commented out 12 | # serve to show the default. 13 | 14 | import sys, os 15 | 16 | # If extensions (or modules to document with autodoc) are in another directory, 17 | # add these directories to sys.path here. If the directory is relative to the 18 | # documentation root, use os.path.abspath to make it absolute, like shown here. 19 | #sys.path.insert(0, os.path.abspath('.')) 20 | 21 | # -- General configuration ----------------------------------------------------- 22 | 23 | # If your documentation needs a minimal Sphinx version, state it here. 24 | #needs_sphinx = '1.0' 25 | 26 | # Add any Sphinx extension module names here, as strings. They can be extensions 27 | # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. 28 | extensions = ['sphinx.ext.doctest', 'sphinx.ext.coverage', 29 | 'sphinx.ext.intersphinx'] 30 | 31 | # Add any paths that contain templates here, relative to this directory. 32 | #templates_path = ['_templates'] 33 | 34 | # The suffix of source filenames. 35 | source_suffix = '.rst' 36 | 37 | # The encoding of source files. 38 | #source_encoding = 'utf-8-sig' 39 | 40 | # The master toctree document. 41 | master_doc = 'index' 42 | 43 | # General information about the project. 44 | project = u'pyblake2' 45 | copyright = u'2013, Dmitry Chestnykh' 46 | 47 | # The version info for the project you're documenting, acts as replacement for 48 | # |version| and |release|, also used in various other places throughout the 49 | # built documents. 50 | # 51 | # The short X.Y version. 52 | version = '0.9' 53 | # The full version, including alpha/beta/rc tags. 54 | release = '0.9' 55 | 56 | # The language for content autogenerated by Sphinx. Refer to documentation 57 | # for a list of supported languages. 58 | #language = None 59 | 60 | # There are two options for replacing |today|: either, you set today to some 61 | # non-false value, then it is used: 62 | #today = '' 63 | # Else, today_fmt is used as the format for a strftime call. 64 | #today_fmt = '%B %d, %Y' 65 | 66 | # List of patterns, relative to source directory, that match files and 67 | # directories to ignore when looking for source files. 68 | exclude_patterns = [] 69 | 70 | # The reST default role (used for this markup: `text`) to use for all documents. 71 | #default_role = None 72 | 73 | # If true, '()' will be appended to :func: etc. cross-reference text. 74 | #add_function_parentheses = True 75 | 76 | # If true, the current module name will be prepended to all description 77 | # unit titles (such as .. function::). 78 | #add_module_names = True 79 | 80 | # If true, sectionauthor and moduleauthor directives will be shown in the 81 | # output. They are ignored by default. 82 | #show_authors = False 83 | 84 | # The name of the Pygments (syntax highlighting) style to use. 85 | pygments_style = 'sphinx' 86 | 87 | # A list of ignored prefixes for module index sorting. 88 | #modindex_common_prefix = [] 89 | 90 | # If true, keep warnings as "system message" paragraphs in the built documents. 91 | #keep_warnings = False 92 | 93 | 94 | # -- Options for HTML output --------------------------------------------------- 95 | 96 | # The theme to use for HTML and HTML Help pages. See the documentation for 97 | # a list of builtin themes. 98 | html_theme = 'default' 99 | 100 | # Theme options are theme-specific and customize the look and feel of a theme 101 | # further. For a list of options available for each theme, see the 102 | # documentation. 103 | #html_theme_options = {} 104 | 105 | # Add any paths that contain custom themes here, relative to this directory. 106 | #html_theme_path = [] 107 | 108 | # The name for this set of Sphinx documents. If None, it defaults to 109 | # " v documentation". 110 | #html_title = None 111 | 112 | # A shorter title for the navigation bar. Default is the same as html_title. 113 | #html_short_title = None 114 | 115 | # The name of an image file (relative to this directory) to place at the top 116 | # of the sidebar. 117 | #html_logo = None 118 | 119 | # The name of an image file (within the static path) to use as favicon of the 120 | # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 121 | # pixels large. 122 | #html_favicon = None 123 | 124 | # Add any paths that contain custom static files (such as style sheets) here, 125 | # relative to this directory. They are copied after the builtin static files, 126 | # so a file named "default.css" will overwrite the builtin "default.css". 127 | #html_static_path = ['_static'] 128 | 129 | # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, 130 | # using the given strftime format. 131 | #html_last_updated_fmt = '%b %d, %Y' 132 | 133 | # If true, SmartyPants will be used to convert quotes and dashes to 134 | # typographically correct entities. 135 | #html_use_smartypants = True 136 | 137 | # Custom sidebar templates, maps document names to template names. 138 | #html_sidebars = {} 139 | 140 | # Additional templates that should be rendered to pages, maps page names to 141 | # template names. 142 | #html_additional_pages = {} 143 | 144 | # If false, no module index is generated. 145 | #html_domain_indices = True 146 | 147 | # If false, no index is generated. 148 | #html_use_index = True 149 | 150 | # If true, the index is split into individual pages for each letter. 151 | #html_split_index = False 152 | 153 | # If true, links to the reST sources are added to the pages. 154 | #html_show_sourcelink = True 155 | 156 | # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. 157 | #html_show_sphinx = True 158 | 159 | # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. 160 | #html_show_copyright = True 161 | 162 | # If true, an OpenSearch description file will be output, and all pages will 163 | # contain a tag referring to it. The value of this option must be the 164 | # base URL from which the finished HTML is served. 165 | #html_use_opensearch = '' 166 | 167 | # This is the file name suffix for HTML files (e.g. ".xhtml"). 168 | #html_file_suffix = None 169 | 170 | # Output file base name for HTML help builder. 171 | htmlhelp_basename = 'pyblake2doc' 172 | 173 | 174 | # -- Options for LaTeX output -------------------------------------------------- 175 | 176 | latex_elements = { 177 | # The paper size ('letterpaper' or 'a4paper'). 178 | #'papersize': 'letterpaper', 179 | 180 | # The font size ('10pt', '11pt' or '12pt'). 181 | #'pointsize': '10pt', 182 | 183 | # Additional stuff for the LaTeX preamble. 184 | #'preamble': '', 185 | } 186 | 187 | # Grouping the document tree into LaTeX files. List of tuples 188 | # (source start file, target name, title, author, documentclass [howto/manual]). 189 | latex_documents = [ 190 | ('index', 'pyblake2.tex', u'pyblake2 Documentation', 191 | u'Dmitry Chestnykh', 'manual'), 192 | ] 193 | 194 | # The name of an image file (relative to this directory) to place at the top of 195 | # the title page. 196 | #latex_logo = None 197 | 198 | # For "manual" documents, if this is true, then toplevel headings are parts, 199 | # not chapters. 200 | #latex_use_parts = False 201 | 202 | # If true, show page references after internal links. 203 | #latex_show_pagerefs = False 204 | 205 | # If true, show URL addresses after external links. 206 | #latex_show_urls = False 207 | 208 | # Documents to append as an appendix to all manuals. 209 | #latex_appendices = [] 210 | 211 | # If false, no module index is generated. 212 | #latex_domain_indices = True 213 | 214 | 215 | # -- Options for manual page output -------------------------------------------- 216 | 217 | # One entry per manual page. List of tuples 218 | # (source start file, name, description, authors, manual section). 219 | man_pages = [ 220 | ('index', 'pyblake2', u'pyblake2 Documentation', 221 | [u'Dmitry Chestnykh'], 1) 222 | ] 223 | 224 | # If true, show URL addresses after external links. 225 | #man_show_urls = False 226 | 227 | 228 | # -- Options for Texinfo output ------------------------------------------------ 229 | 230 | # Grouping the document tree into Texinfo files. List of tuples 231 | # (source start file, target name, title, author, 232 | # dir menu entry, description, category) 233 | texinfo_documents = [ 234 | ('index', 'pyblake2', u'pyblake2 Documentation', 235 | u'Dmitry Chestnykh', 'pyblake2', 'One line description of project.', 236 | 'Miscellaneous'), 237 | ] 238 | 239 | # Documents to append as an appendix to all manuals. 240 | #texinfo_appendices = [] 241 | 242 | # If false, no module index is generated. 243 | #texinfo_domain_indices = True 244 | 245 | # How to display URL addresses: 'footnote', 'no', or 'inline'. 246 | #texinfo_show_urls = 'footnote' 247 | 248 | # If true, do not generate a @detailmenu in the "Top" node's menu. 249 | #texinfo_no_detailmenu = False 250 | 251 | 252 | # --- Intersphinx extension -------- 253 | 254 | intersphinx_mapping = {'python': ('http://docs.python.org/3.3', None)} 255 | -------------------------------------------------------------------------------- /doc_src/credits.rst: -------------------------------------------------------------------------------- 1 | Credits 2 | ======= 3 | 4 | BLAKE2_ was designed by *Jean-Philippe Aumasson*, *Samuel Neves*, *Zooko 5 | Wilcox-O'Hearn*, and *Christian Winnerlein* based on SHA-3_ finalist BLAKE_ 6 | created by *Jean-Philippe Aumasson*, *Luca Henzen*, *Willi Meier*, and 7 | *Raphael C.-W. Phan*. 8 | 9 | It uses core algorithm from ChaCha_ cipher designed by *Daniel J. Bernstein*. 10 | 11 | Python extension module was written by *Dmitry Chestnykh* based on C 12 | implementation written by *Samuel Neves*. 13 | 14 | The following public domain dedication applies for both C hash function 15 | implementation, extension code, and this documentation: 16 | 17 | To the extent possible under law, the author(s) have dedicated all copyright 18 | and related and neighboring rights to this software to the public domain 19 | worldwide. This software is distributed without any warranty. 20 | 21 | You should have received a copy of the CC0 Public Domain Dedication along 22 | with this software. If not, see 23 | http://creativecommons.org/publicdomain/zero/1.0/. 24 | 25 | The following people have helped with development or contributed their changes 26 | to the project and the public domain according to the Creative Commons Public 27 | Domain Dedication 1.0 Universal: 28 | 29 | * *Alexandr Sokolovskiy* 30 | 31 | .. seealso:: Official BLAKE2 website: https://blake2.net 32 | 33 | .. _BLAKE2: https://blake2.net 34 | .. _BLAKE: https://131002.net/blake/ 35 | .. _SHA-3: http://en.wikipedia.org/wiki/NIST_hash_function_competition 36 | .. _ChaCha: http://cr.yp.to/chacha.html 37 | 38 | 39 | -------------------------------------------------------------------------------- /doc_src/examples.rst: -------------------------------------------------------------------------------- 1 | Examples 2 | ======== 3 | 4 | .. module:: pyblake2 5 | 6 | Simple hashing 7 | -------------- 8 | 9 | To calculate hash of some data, you should first construct a hash object by 10 | calling the appropriate constructor function (:func:`blake2b` or 11 | :func:`blake2s`), then update it with the data by calling :meth:`update` on the 12 | object, and, finally, get the digest out of the object by calling 13 | :meth:`digest` (or :meth:`hexdigest` for hex-encoded string). 14 | 15 | >>> from pyblake2 import blake2b 16 | >>> h = blake2b() 17 | >>> h.update(b'Hello world') 18 | >>> h.hexdigest() 19 | '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183' 20 | 21 | 22 | As a shortcut, you can pass the first chunk of data to update directly to the 23 | constructor as the first argument (or as `data` keyword argument): 24 | 25 | >>> from pyblake2 import blake2b 26 | >>> blake2b(b'Hello world').hexdigest() 27 | '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183' 28 | 29 | You can call :meth:`hash.update` as many times as you need to iteratively 30 | update the hash: 31 | 32 | >>> from pyblake2 import blake2b 33 | >>> items = [b'Hello', b' ', b'world'] 34 | >>> h = blake2b() 35 | >>> for item in items: 36 | ... h.update(item) 37 | >>> h.hexdigest() 38 | '6ff843ba685842aa82031d3f53c48b66326df7639a63d128974c5c14f31a0f33343a8c65551134ed1ae0f2b0dd2bb495dc81039e3eeb0aa1bb0388bbeac29183' 39 | 40 | 41 | Using different digest sizes 42 | ---------------------------- 43 | 44 | BLAKE2 has configurable size of digests up to 64 bytes for BLAKE2b and up to 32 45 | bytes for BLAKE2s. For example, to replace SHA-1 with BLAKE2b without changing 46 | the size of output, we can tell BLAKE2b to produce 20-byte digests: 47 | 48 | >>> from pyblake2 import blake2b 49 | >>> h = blake2b(digest_size=20) 50 | >>> h.update(b'Replacing SHA1 with the more secure function') 51 | >>> h.hexdigest() 52 | 'd24f26cf8de66472d58d4e1b1774b4c9158b1f4c' 53 | >>> h.digest_size 54 | 20 55 | >>> len(h.digest()) 56 | 20 57 | 58 | Hash objects with different digest sizes have completely different outputs 59 | (shorter hashes are *not* prefixes of longer hashes); BLAKE2b and BLAKE2s 60 | produce different outputs even if the output length is the same: 61 | 62 | >>> from pyblake2 import blake2b, blake2s 63 | >>> blake2b(digest_size=10).hexdigest() 64 | '6fa1d8fcfd719046d762' 65 | >>> blake2b(digest_size=11).hexdigest() 66 | 'eb6ec15daf9546254f0809' 67 | >>> blake2s(digest_size=10).hexdigest() 68 | '1bf21a98c78a1c376ae9' 69 | >>> blake2s(digest_size=11).hexdigest() 70 | '567004bf96e4a25773ebf4' 71 | 72 | 73 | Keyed hashing 74 | ------------- 75 | 76 | Keyed hashing can be used for authentication as a faster and simpler 77 | replacement for `Hash-based message authentication code 78 | `_ (HMAC). 79 | BLAKE2 can be securely used in prefix-MAC mode thanks to the 80 | indifferentiability property inherited from BLAKE. 81 | 82 | This example shows how to get a (hex-encoded) 128-bit authentication code for 83 | message ``b'message data'`` with key ``b'pseudorandom key'``: 84 | 85 | >>> from pyblake2 import blake2b 86 | >>> h = blake2b(key=b'pseudorandom key', digest_size=16) 87 | >>> h.update(b'message data') 88 | >>> h.hexdigest() 89 | '3d363ff7401e02026f4a4687d4863ced' 90 | 91 | 92 | As a practical example, a web application can symmetrically sign cookies sent 93 | to users and later verify them to make sure they weren't tampered with: 94 | 95 | >>> from pyblake2 import blake2b 96 | >>> 97 | >>> SECRET_KEY = b'pseudorandomly generated server secret key' 98 | >>> AUTH_SIZE = 16 99 | >>> 100 | >>> def sign(cookie): 101 | ... h = blake2b(data=cookie, digest_size=AUTH_SIZE, key=SECRET_KEY) 102 | ... return h.hexdigest() 103 | >>> 104 | >>> def verify(cookie, sig): 105 | ... good_sig = sign(cookie) 106 | ... if len(sig) != len(good_sig): 107 | ... return False 108 | ... # Use constant-time comparison to avoid timing attacks. 109 | ... result = 0 110 | ... for x, y in zip(sig, good_sig): 111 | ... result |= ord(x) ^ ord(y) 112 | ... return result == 0 113 | >>> 114 | >>> cookie = b'user:vatrogasac' 115 | >>> sig = sign(cookie) 116 | >>> print("{0},{1}".format(cookie.decode('utf-8'), sig)) 117 | user:vatrogasac,349cf904533767ed2d755279a8df84d0 118 | >>> verify(cookie, sig) 119 | True 120 | >>> verify(b'user:policajac', sig) 121 | False 122 | >>> verify(cookie, '0102030405060708090a0b0c0d0e0f00') 123 | False 124 | 125 | Even though there's a native keyed hashing mode, BLAKE2 can, of course, be used 126 | in HMAC construction with :mod:`hmac` module from the standard library: 127 | 128 | >>> import hmac, pyblake2 129 | >>> m = hmac.new(b'secret key', digestmod=pyblake2.blake2s) 130 | >>> m.update(b'message') 131 | >>> m.hexdigest() 132 | 'e3c8102868d28b5ff85fc35dda07329970d1a01e273c37481326fe0c861c8142' 133 | 134 | 135 | Randomized hashing 136 | ------------------ 137 | 138 | By setting `salt` parameter users can introduce randomization to the hash 139 | function. Randomized hashing is useful for protecting against collision attacks 140 | on the hash function used in digital signatures. 141 | 142 | Randomized hashing is designed for situations where one party, the message 143 | preparer, generates all or part of a message to be signed by a second 144 | party, the message signer. If the message preparer is able to find 145 | cryptographic hash function collisions (i.e., two messages producing the 146 | same hash value), then she might prepare meaningful versions of the message 147 | that would produce the same hash value and digital signature, but with 148 | different results (e.g., transferring $1,000,000 to an account, rather than 149 | $10). Cryptographic hash functions have been designed with collision 150 | resistance as a major goal, but the current concentration on attacking 151 | cryptographic hash functions may result in a given cryptographic hash 152 | function providing less collision resistance than expected. Randomized 153 | hashing offers the signer additional protection by reducing the likelihood 154 | that a preparer can generate two or more messages that ultimately yield the 155 | same hash value during the digital signature generation process – even if 156 | it is practical to find collisions for the hash function. However, the use 157 | of randomized hashing may reduce the amount of security provided by a 158 | digital signature when all portions of the message are prepared 159 | by the signer. 160 | 161 | (`NIST SP-800-106 "Randomized Hashing for Digital Signatures" 162 | `_) 163 | 164 | In BLAKE2 the salt is processed as a one-time input to the hash function during 165 | initialization, rather than as an input to each compression function. 166 | 167 | .. warning:: 168 | 169 | *Salted hashing* (or just hashing) with BLAKE2 or any other general-purpose 170 | cryptographic hash function, such as SHA-256, is not suitable for hashing 171 | passwords. See `BLAKE2 FAQ `_ for more 172 | information. 173 | .. 174 | 175 | >>> import os 176 | >>> from pyblake2 import blake2b, BLAKE2B_SALT_SIZE 177 | >>> msg = b'some message' 178 | >>> # Calculate the first hash with a random salt. 179 | >>> salt1 = os.urandom(BLAKE2B_SALT_SIZE) 180 | >>> h1 = blake2b(salt=salt1) 181 | >>> h1.update(msg) 182 | >>> # Calculate the second hash with a different random salt. 183 | >>> salt2 = os.urandom(BLAKE2B_SALT_SIZE) 184 | >>> h2 = blake2b(salt=salt2) 185 | >>> h2.update(msg) 186 | >>> # The digests are different. 187 | >>> h1.digest() != h2.digest() 188 | True 189 | 190 | 191 | Personalization 192 | --------------- 193 | 194 | Sometimes it is useful to force hash function to produce different digests for 195 | the same input for different purposes. Quoting the authors of the Skein hash 196 | function: 197 | 198 | We recommend that all application designers seriously consider doing this; 199 | we have seen many protocols where a hash that is computed in one part of 200 | the protocol can be used in an entirely different part because two hash 201 | computations were done on similar or related data, and the attacker can 202 | force the application to make the hash inputs the same. Personalizing each 203 | hash function used in the protocol summarily stops this type of attack. 204 | 205 | (`The Skein Hash Function Family 206 | `_, 207 | p. 21) 208 | 209 | BLAKE2 can be personalized by passing bytes to the *person* argument: 210 | 211 | >>> from pyblake2 import blake2b 212 | >>> FILES_HASH_PERSON = b'MyApp Files Hash' 213 | >>> BLOCK_HASH_PERSON = b'MyApp Block Hash' 214 | >>> h = blake2b(digest_size=32, person=FILES_HASH_PERSON) 215 | >>> h.update(b'the same content') 216 | >>> h.hexdigest() 217 | '20d9cd024d4fb086aae819a1432dd2466de12947831b75c5a30cf2676095d3b4' 218 | >>> h = blake2b(digest_size=32, person=BLOCK_HASH_PERSON) 219 | >>> h.update(b'the same content') 220 | >>> h.hexdigest() 221 | 'cf68fb5761b9c44e7878bfb2c4c9aea52264a80b75005e65619778de59f383a3' 222 | 223 | Personalization together with the keyed mode can also be used to derive different 224 | keys from a single one. 225 | 226 | >>> from pyblake2 import blake2s 227 | >>> from base64 import b64decode, b64encode 228 | >>> orig_key = b64decode(b'Rm5EPJai72qcK3RGBpW3vPNfZy5OZothY+kHY6h21KM=') 229 | >>> enc_key = blake2s(key=orig_key, person=b'kEncrypt').digest() 230 | >>> mac_key = blake2s(key=orig_key, person=b'kMAC').digest() 231 | >>> print(b64encode(enc_key).decode('utf-8')) 232 | rbPb15S/Z9t+agffno5wuhB77VbRi6F9Iv2qIxU7WHw= 233 | >>> print(b64encode(mac_key).decode('utf-8')) 234 | G9GtHFE1YluXY1zWPlYk1e/nWfu0WSEb0KRcjhDeP/o= 235 | 236 | Tree mode 237 | --------- 238 | 239 | Here's an example of hashing a minimal tree with two leaf nodes:: 240 | 241 | 10 242 | / \ 243 | 00 01 244 | 245 | The example uses 64-byte internal digests, and returns the 32-byte final 246 | digest. 247 | 248 | >>> from pyblake2 import blake2b 249 | >>> 250 | >>> FANOUT = 2 251 | >>> DEPTH = 2 252 | >>> LEAF_SIZE = 4096 253 | >>> INNER_SIZE = 64 254 | >>> 255 | >>> buf = bytearray(6000) 256 | >>> 257 | >>> # Left leaf 258 | ... h00 = blake2b(buf[0:LEAF_SIZE], fanout=FANOUT, depth=DEPTH, 259 | ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, 260 | ... node_offset=0, node_depth=0, last_node=False) 261 | >>> # Right leaf 262 | ... h01 = blake2b(buf[LEAF_SIZE:], fanout=FANOUT, depth=DEPTH, 263 | ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, 264 | ... node_offset=1, node_depth=0, last_node=True) 265 | >>> # Root node 266 | ... h10 = blake2b(digest_size=32, fanout=FANOUT, depth=DEPTH, 267 | ... leaf_size=LEAF_SIZE, inner_size=INNER_SIZE, 268 | ... node_offset=0, node_depth=1, last_node=True) 269 | >>> h10.update(h00.digest()) 270 | >>> h10.update(h01.digest()) 271 | >>> h10.hexdigest() 272 | '3ad2a9b37c6070e374c7a8c508fe20ca86b6ed54e286e93a0318e95e881db5aa' 273 | -------------------------------------------------------------------------------- /doc_src/index.rst: -------------------------------------------------------------------------------- 1 | pyblake2 — BLAKE2 hash function for Python 2 | ========================================== 3 | 4 | pyblake2 is an extension module for Python implementing BLAKE2 hash function. 5 | 6 | BLAKE2_ is a cryptographic hash function, which offers highest security while 7 | being as fast as MD5 or SHA-1, and comes in two flavors: 8 | 9 | * **BLAKE2b**, optimized for 64-bit platforms and produces digests of any size 10 | between 1 and 64 bytes, 11 | 12 | * **BLAKE2s**, optimized for 8- to 32-bit platforms and produces digests of any 13 | size between 1 and 32 bytes. 14 | 15 | BLAKE2 supports **keyed mode** (a faster and simpler replacement for HMAC_), 16 | **salted hashing**, **personalization**, and **tree hashing**. 17 | 18 | Hash objects from this module follow the API of standard library's 19 | :mod:`hashlib` objects. 20 | 21 | .. _BLAKE2: https://blake2.net 22 | .. _HMAC: http://en.wikipedia.org/wiki/Hash-based_message_authentication_code 23 | 24 | Contents: 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | 29 | module 30 | examples 31 | installation 32 | credits 33 | -------------------------------------------------------------------------------- /doc_src/installation.rst: -------------------------------------------------------------------------------- 1 | Installation 2 | ============ 3 | 4 | :mod:`pyblake2` works with Python 2.6, 2.7 and 3.x. 5 | 6 | You can install it from PyPi using `pip `_:: 7 | 8 | $ pip install pyblake2 9 | 10 | or download sources and run:: 11 | 12 | $ python setup.py install 13 | 14 | 15 | Download 16 | -------- 17 | 18 | See list of files here: 19 | 20 | https://pypi.python.org/pypi/pyblake2 21 | 22 | 23 | Development 24 | ----------- 25 | 26 | **Git repository:** https://github.com/dchest/pyblake2 27 | 28 | When submitting pull requests, please include public domain dedication / CC0 29 | header text as written in the :doc:`credits` topic into the text of your pull 30 | request, including your full legal name. (We cannot accept changes if you are 31 | not willing to place them into the public domain.) 32 | 33 | Version history 34 | --------------- 35 | 36 | 0.9.3: 37 | 38 | * Build SSE2 implementation on x86_64 architectures by default. 39 | 40 | 0.9.2: 41 | 42 | * Made tests compatible with Python 2.6 and 3.2. 43 | * Made examples from documentation compatible with Python 3. 44 | * Removed compiled documentation from source distribution. 45 | 46 | 0.9.1: 47 | 48 | * Fixed Windows build. 49 | 50 | 0.9.0: 51 | 52 | * First release. 53 | -------------------------------------------------------------------------------- /doc_src/module.rst: -------------------------------------------------------------------------------- 1 | Module 2 | ====== 3 | 4 | .. module:: pyblake2 5 | 6 | Creating hash objects 7 | --------------------- 8 | 9 | New hash objects are created by calling constructor functions: 10 | 11 | 12 | .. function:: blake2b(data=b'', digest_size=64, key=b'', salt=b'', \ 13 | person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \ 14 | node_depth=0, inner_size=0, last_node=False) 15 | 16 | .. function:: blake2s(data=b'', digest_size=32, key=b'', salt=b'', \ 17 | person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \ 18 | node_depth=0, inner_size=0, last_node=False) 19 | 20 | 21 | These functions return the corresponding hash objects for calculating 22 | BLAKE2b or BLAKE2s. They optionally take these general parameters: 23 | 24 | * `data`: initial chunk of data to hash, which must be interpretable as buffer 25 | of bytes. 26 | 27 | * `digest_size`: size of output digest in bytes. 28 | 29 | * `key`: key for keyed hashing (up to 64 bytes for BLAKE2b, up to 32 bytes for 30 | BLAKE2s). 31 | 32 | * `salt`: salt for randomized hashing (up to 16 bytes for BLAKE2b, up to 8 33 | bytes for BLAKE2s). 34 | 35 | * `person`: personalization string (up to 16 bytes for BLAKE2b, up to 8 bytes 36 | for BLAKE2s). 37 | 38 | The following table shows limits for general parameters (in bytes): 39 | 40 | ======= =========== ======== ========= =========== 41 | Hash digest_size len(key) len(salt) len(person) 42 | ======= =========== ======== ========= =========== 43 | BLAKE2b 64 64 16 16 44 | BLAKE2s 32 32 8 8 45 | ======= =========== ======== ========= =========== 46 | 47 | .. note:: 48 | 49 | BLAKE2 specification defines constant lengths for salt and personalization 50 | parameters, however, for convenience, this implementation accepts byte 51 | strings of any size up to the specified length. If the length of the 52 | parameter is less than specified, it is padded with zeros, thus, for 53 | example, ``b'salt'`` and ``b'salt\x00'`` is the same value. (This is not 54 | the case for `key`.) 55 | 56 | These sizes are available as module `constants`_ described below. 57 | 58 | Constructor functions also accept the following tree hashing parameters: 59 | 60 | * `fanout`: fanout (0 to 255, 0 if unlimited, 1 in sequential mode). 61 | 62 | * `depth`: maximal depth of tree (1 to 255, 255 if unlimited, 1 in 63 | sequential mode). 64 | 65 | * `leaf_size`: maximal byte length of leaf (0 to 2**32-1, 0 if unlimited or in 66 | sequential mode). 67 | 68 | * `node_offset`: node offset (0 to 2**64-1 for BLAKE2b, 0 to 2**48-1 for 69 | BLAKE2s, 0 for the first, leftmost, leaf, or in sequential mode). 70 | 71 | * `node_depth`: node depth (0 to 255, 0 for leaves, or in sequential mode). 72 | 73 | * `inner_size`: inner digest size (0 to 64 for BLAKE2b, 0 to 32 for 74 | BLAKE2s, 0 in sequential mode). 75 | 76 | * `last_node`: boolean indicating whether the processed node is the last 77 | one (`False` for sequential mode). 78 | 79 | .. figure:: tree.png 80 | :alt: Explanation of tree mode parameters. 81 | 82 | See section 2.10 in `BLAKE2 specification 83 | `_ for comprehensive review of tree 84 | hashing. 85 | 86 | 87 | Using hash objects 88 | ------------------ 89 | 90 | Hash objects have the following attributes and methods: 91 | 92 | 93 | .. data:: hash.digest_size 94 | 95 | The size of the resulting digest in bytes. This is the value given to hash 96 | object constructor in `digest_size` argument. 97 | 98 | 99 | .. data:: hash.block_size 100 | 101 | The internal block size of the hash algorithm in bytes. 102 | 103 | 104 | .. method:: hash.update(arg) 105 | 106 | Update the hash object with the object, which must be interpretable as buffer 107 | of bytes 108 | 109 | .. note:: 110 | 111 | For better multithreading performance, the Python GIL is released for data 112 | larger than 2047 bytes at hash object creation or on update to allow other 113 | threads to run. 114 | 115 | 116 | .. method:: hash.digest() 117 | 118 | Return the digest of the data so far. 119 | 120 | 121 | .. method:: hash.hexdigest() 122 | 123 | Like :meth:`digest` except the digest is returned as a string of double 124 | length, containing only hexadecimal digits. 125 | 126 | 127 | .. method:: hash.copy() 128 | 129 | Return a copy of the hash object. 130 | 131 | 132 | Constants 133 | --------- 134 | 135 | .. data:: BLAKE2B_SALT_SIZE 136 | .. data:: BLAKE2S_SALT_SIZE 137 | 138 | Salt length (maximum length accepted by constructors). 139 | 140 | 141 | .. data:: BLAKE2B_PERSON_SIZE 142 | .. data:: BLAKE2S_PERSON_SIZE 143 | 144 | Personalization string length (maximum length accepted by constructors). 145 | 146 | 147 | .. data:: BLAKE2B_MAX_KEY_SIZE 148 | .. data:: BLAKE2S_MAX_KEY_SIZE 149 | 150 | Maximum key size. 151 | 152 | 153 | .. data:: BLAKE2B_MAX_DIGEST_SIZE 154 | .. data:: BLAKE2S_MAX_DIGEST_SIZE 155 | 156 | Maximum digest size that the hash function can output. 157 | 158 | 159 | -------------------------------------------------------------------------------- /doc_src/tree.odg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchest/pyblake2/646d0a55da24196c5312b35573598cd18f8137b1/doc_src/tree.odg -------------------------------------------------------------------------------- /doc_src/tree.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dchest/pyblake2/646d0a55da24196c5312b35573598cd18f8137b1/doc_src/tree.png -------------------------------------------------------------------------------- /impl/blake2-config.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2_CONFIG_H__ 17 | #define __BLAKE2_CONFIG_H__ 18 | 19 | #ifdef HAVE_AVX2 20 | #ifndef HAVE_AVX 21 | #define HAVE_AVX 22 | #endif 23 | #endif 24 | 25 | #ifdef HAVE_XOP 26 | #ifndef HAVE_AVX 27 | #define HAVE_AVX 28 | #endif 29 | #endif 30 | 31 | #ifdef HAVE_AVX 32 | #ifndef HAVE_SSE41 33 | #define HAVE_SSE41 34 | #endif 35 | #endif 36 | 37 | #ifdef HAVE_SSE41 38 | #ifndef HAVE_SSSE3 39 | #define HAVE_SSSE3 40 | #endif 41 | #endif 42 | 43 | #ifdef HAVE_SSSE3 44 | #define HAVE_SSE2 45 | #endif 46 | 47 | #endif 48 | -------------------------------------------------------------------------------- /impl/blake2-impl.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2_IMPL_H__ 17 | #define __BLAKE2_IMPL_H__ 18 | 19 | #include 20 | 21 | BLAKE2_LOCAL_INLINE(uint32_t) load32( const void *src ) 22 | { 23 | #if defined(NATIVE_LITTLE_ENDIAN) 24 | uint32_t w; 25 | memcpy(&w, src, sizeof w); 26 | return w; 27 | #else 28 | const uint8_t *p = ( const uint8_t * )src; 29 | uint32_t w = *p++; 30 | w |= ( uint32_t )( *p++ ) << 8; 31 | w |= ( uint32_t )( *p++ ) << 16; 32 | w |= ( uint32_t )( *p++ ) << 24; 33 | return w; 34 | #endif 35 | } 36 | 37 | BLAKE2_LOCAL_INLINE(uint64_t) load64( const void *src ) 38 | { 39 | #if defined(NATIVE_LITTLE_ENDIAN) 40 | uint64_t w; 41 | memcpy(&w, src, sizeof w); 42 | return w; 43 | #else 44 | const uint8_t *p = ( const uint8_t * )src; 45 | uint64_t w = *p++; 46 | w |= ( uint64_t )( *p++ ) << 8; 47 | w |= ( uint64_t )( *p++ ) << 16; 48 | w |= ( uint64_t )( *p++ ) << 24; 49 | w |= ( uint64_t )( *p++ ) << 32; 50 | w |= ( uint64_t )( *p++ ) << 40; 51 | w |= ( uint64_t )( *p++ ) << 48; 52 | w |= ( uint64_t )( *p++ ) << 56; 53 | return w; 54 | #endif 55 | } 56 | 57 | BLAKE2_LOCAL_INLINE(void) store32( void *dst, uint32_t w ) 58 | { 59 | #if defined(NATIVE_LITTLE_ENDIAN) 60 | memcpy(dst, &w, sizeof w); 61 | #else 62 | uint8_t *p = ( uint8_t * )dst; 63 | *p++ = ( uint8_t )w; w >>= 8; 64 | *p++ = ( uint8_t )w; w >>= 8; 65 | *p++ = ( uint8_t )w; w >>= 8; 66 | *p++ = ( uint8_t )w; 67 | #endif 68 | } 69 | 70 | BLAKE2_LOCAL_INLINE(void) store64( void *dst, uint64_t w ) 71 | { 72 | #if defined(NATIVE_LITTLE_ENDIAN) 73 | memcpy(dst, &w, sizeof w); 74 | #else 75 | uint8_t *p = ( uint8_t * )dst; 76 | *p++ = ( uint8_t )w; w >>= 8; 77 | *p++ = ( uint8_t )w; w >>= 8; 78 | *p++ = ( uint8_t )w; w >>= 8; 79 | *p++ = ( uint8_t )w; w >>= 8; 80 | *p++ = ( uint8_t )w; w >>= 8; 81 | *p++ = ( uint8_t )w; w >>= 8; 82 | *p++ = ( uint8_t )w; w >>= 8; 83 | *p++ = ( uint8_t )w; 84 | #endif 85 | } 86 | 87 | BLAKE2_LOCAL_INLINE(uint64_t) load48( const void *src ) 88 | { 89 | const uint8_t *p = ( const uint8_t * )src; 90 | uint64_t w = *p++; 91 | w |= ( uint64_t )( *p++ ) << 8; 92 | w |= ( uint64_t )( *p++ ) << 16; 93 | w |= ( uint64_t )( *p++ ) << 24; 94 | w |= ( uint64_t )( *p++ ) << 32; 95 | w |= ( uint64_t )( *p++ ) << 40; 96 | return w; 97 | } 98 | 99 | BLAKE2_LOCAL_INLINE(void) store48( void *dst, uint64_t w ) 100 | { 101 | uint8_t *p = ( uint8_t * )dst; 102 | *p++ = ( uint8_t )w; w >>= 8; 103 | *p++ = ( uint8_t )w; w >>= 8; 104 | *p++ = ( uint8_t )w; w >>= 8; 105 | *p++ = ( uint8_t )w; w >>= 8; 106 | *p++ = ( uint8_t )w; w >>= 8; 107 | *p++ = ( uint8_t )w; 108 | } 109 | 110 | BLAKE2_LOCAL_INLINE(uint32_t) rotl32( const uint32_t w, const unsigned c ) 111 | { 112 | return ( w << c ) | ( w >> ( 32 - c ) ); 113 | } 114 | 115 | BLAKE2_LOCAL_INLINE(uint64_t) rotl64( const uint64_t w, const unsigned c ) 116 | { 117 | return ( w << c ) | ( w >> ( 64 - c ) ); 118 | } 119 | 120 | BLAKE2_LOCAL_INLINE(uint32_t) rotr32( const uint32_t w, const unsigned c ) 121 | { 122 | return ( w >> c ) | ( w << ( 32 - c ) ); 123 | } 124 | 125 | BLAKE2_LOCAL_INLINE(uint64_t) rotr64( const uint64_t w, const unsigned c ) 126 | { 127 | return ( w >> c ) | ( w << ( 64 - c ) ); 128 | } 129 | 130 | /* prevents compiler optimizing out memset() */ 131 | BLAKE2_LOCAL_INLINE(void) secure_zero_memory(void *v, size_t n) 132 | { 133 | static void *(*const volatile memset_v)(void *, int, size_t) = &memset; 134 | memset_v(v, 0, n); 135 | } 136 | 137 | #endif 138 | 139 | -------------------------------------------------------------------------------- /impl/blake2.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2_H__ 17 | #define __BLAKE2_H__ 18 | 19 | #include 20 | 21 | #include "blake2-config.h" 22 | 23 | #ifdef BLAKE2_NO_INLINE 24 | #define BLAKE2_LOCAL_INLINE(type) static type 25 | #endif 26 | 27 | #ifndef BLAKE2_LOCAL_INLINE 28 | #define BLAKE2_LOCAL_INLINE(type) static inline type 29 | #endif 30 | 31 | #if defined(__cplusplus) 32 | extern "C" { 33 | #endif 34 | 35 | enum blake2s_constant 36 | { 37 | BLAKE2S_BLOCKBYTES = 64, 38 | BLAKE2S_OUTBYTES = 32, 39 | BLAKE2S_KEYBYTES = 32, 40 | BLAKE2S_SALTBYTES = 8, 41 | BLAKE2S_PERSONALBYTES = 8 42 | }; 43 | 44 | enum blake2b_constant 45 | { 46 | BLAKE2B_BLOCKBYTES = 128, 47 | BLAKE2B_OUTBYTES = 64, 48 | BLAKE2B_KEYBYTES = 64, 49 | BLAKE2B_SALTBYTES = 16, 50 | BLAKE2B_PERSONALBYTES = 16 51 | }; 52 | 53 | typedef struct __blake2s_state 54 | { 55 | uint32_t h[8]; 56 | uint32_t t[2]; 57 | uint32_t f[2]; 58 | uint8_t buf[2 * BLAKE2S_BLOCKBYTES]; 59 | size_t buflen; 60 | uint8_t last_node; 61 | } blake2s_state; 62 | 63 | typedef struct __blake2b_state 64 | { 65 | uint64_t h[8]; 66 | uint64_t t[2]; 67 | uint64_t f[2]; 68 | uint8_t buf[2 * BLAKE2B_BLOCKBYTES]; 69 | size_t buflen; 70 | uint8_t last_node; 71 | } blake2b_state; 72 | 73 | typedef struct __blake2sp_state 74 | { 75 | blake2s_state S[8][1]; 76 | blake2s_state R[1]; 77 | uint8_t buf[8 * BLAKE2S_BLOCKBYTES]; 78 | size_t buflen; 79 | } blake2sp_state; 80 | 81 | typedef struct __blake2bp_state 82 | { 83 | blake2b_state S[4][1]; 84 | blake2b_state R[1]; 85 | uint8_t buf[4 * BLAKE2B_BLOCKBYTES]; 86 | size_t buflen; 87 | } blake2bp_state; 88 | 89 | 90 | #pragma pack(push, 1) 91 | typedef struct __blake2s_param 92 | { 93 | uint8_t digest_length; /* 1 */ 94 | uint8_t key_length; /* 2 */ 95 | uint8_t fanout; /* 3 */ 96 | uint8_t depth; /* 4 */ 97 | uint32_t leaf_length; /* 8 */ 98 | uint8_t node_offset[6];// 14 99 | uint8_t node_depth; /* 15 */ 100 | uint8_t inner_length; /* 16 */ 101 | /* uint8_t reserved[0]; */ 102 | uint8_t salt[BLAKE2S_SALTBYTES]; /* 24 */ 103 | uint8_t personal[BLAKE2S_PERSONALBYTES]; /* 32 */ 104 | } blake2s_param; 105 | 106 | typedef struct __blake2b_param 107 | { 108 | uint8_t digest_length; /* 1 */ 109 | uint8_t key_length; /* 2 */ 110 | uint8_t fanout; /* 3 */ 111 | uint8_t depth; /* 4 */ 112 | uint32_t leaf_length; /* 8 */ 113 | uint64_t node_offset; /* 16 */ 114 | uint8_t node_depth; /* 17 */ 115 | uint8_t inner_length; /* 18 */ 116 | uint8_t reserved[14]; /* 32 */ 117 | uint8_t salt[BLAKE2B_SALTBYTES]; /* 48 */ 118 | uint8_t personal[BLAKE2B_PERSONALBYTES]; /* 64 */ 119 | } blake2b_param; 120 | #pragma pack(pop) 121 | 122 | /* Streaming API */ 123 | int blake2s_init( blake2s_state *S, const uint8_t outlen ); 124 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 125 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); 126 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ); 127 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ); 128 | 129 | int blake2b_init( blake2b_state *S, const uint8_t outlen ); 130 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 131 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); 132 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ); 133 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ); 134 | 135 | int blake2sp_init( blake2sp_state *S, const uint8_t outlen ); 136 | int blake2sp_init_key( blake2sp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 137 | int blake2sp_update( blake2sp_state *S, const uint8_t *in, uint64_t inlen ); 138 | int blake2sp_final( blake2sp_state *S, uint8_t *out, uint8_t outlen ); 139 | 140 | int blake2bp_init( blake2bp_state *S, const uint8_t outlen ); 141 | int blake2bp_init_key( blake2bp_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ); 142 | int blake2bp_update( blake2bp_state *S, const uint8_t *in, uint64_t inlen ); 143 | int blake2bp_final( blake2bp_state *S, uint8_t *out, uint8_t outlen ); 144 | 145 | /* Simple API */ 146 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 147 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 148 | 149 | int blake2sp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 150 | int blake2bp( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ); 151 | 152 | static inline int blake2( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 153 | { 154 | return blake2b( out, in, key, outlen, inlen, keylen ); 155 | } 156 | 157 | #if defined(__cplusplus) 158 | } 159 | #endif 160 | 161 | #endif 162 | 163 | -------------------------------------------------------------------------------- /impl/blake2b-load-sse2.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2B_LOAD_SSE2_H__ 17 | #define __BLAKE2B_LOAD_SSE2_H__ 18 | 19 | #define LOAD_MSG_0_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4) 20 | #define LOAD_MSG_0_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5) 21 | #define LOAD_MSG_0_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12) 22 | #define LOAD_MSG_0_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13) 23 | #define LOAD_MSG_1_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9) 24 | #define LOAD_MSG_1_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15) 25 | #define LOAD_MSG_1_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11) 26 | #define LOAD_MSG_1_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7) 27 | #define LOAD_MSG_2_1(b0, b1) b0 = _mm_set_epi64x(m12, m11); b1 = _mm_set_epi64x(m15, m5) 28 | #define LOAD_MSG_2_2(b0, b1) b0 = _mm_set_epi64x(m0, m8); b1 = _mm_set_epi64x(m13, m2) 29 | #define LOAD_MSG_2_3(b0, b1) b0 = _mm_set_epi64x(m3, m10); b1 = _mm_set_epi64x(m9, m7) 30 | #define LOAD_MSG_2_4(b0, b1) b0 = _mm_set_epi64x(m6, m14); b1 = _mm_set_epi64x(m4, m1) 31 | #define LOAD_MSG_3_1(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m13) 32 | #define LOAD_MSG_3_2(b0, b1) b0 = _mm_set_epi64x(m1, m9); b1 = _mm_set_epi64x(m14, m12) 33 | #define LOAD_MSG_3_3(b0, b1) b0 = _mm_set_epi64x(m5, m2); b1 = _mm_set_epi64x(m15, m4) 34 | #define LOAD_MSG_3_4(b0, b1) b0 = _mm_set_epi64x(m10, m6); b1 = _mm_set_epi64x(m8, m0) 35 | #define LOAD_MSG_4_1(b0, b1) b0 = _mm_set_epi64x(m5, m9); b1 = _mm_set_epi64x(m10, m2) 36 | #define LOAD_MSG_4_2(b0, b1) b0 = _mm_set_epi64x(m7, m0); b1 = _mm_set_epi64x(m15, m4) 37 | #define LOAD_MSG_4_3(b0, b1) b0 = _mm_set_epi64x(m11, m14); b1 = _mm_set_epi64x(m3, m6) 38 | #define LOAD_MSG_4_4(b0, b1) b0 = _mm_set_epi64x(m12, m1); b1 = _mm_set_epi64x(m13, m8) 39 | #define LOAD_MSG_5_1(b0, b1) b0 = _mm_set_epi64x(m6, m2); b1 = _mm_set_epi64x(m8, m0) 40 | #define LOAD_MSG_5_2(b0, b1) b0 = _mm_set_epi64x(m10, m12); b1 = _mm_set_epi64x(m3, m11) 41 | #define LOAD_MSG_5_3(b0, b1) b0 = _mm_set_epi64x(m7, m4); b1 = _mm_set_epi64x(m1, m15) 42 | #define LOAD_MSG_5_4(b0, b1) b0 = _mm_set_epi64x(m5, m13); b1 = _mm_set_epi64x(m9, m14) 43 | #define LOAD_MSG_6_1(b0, b1) b0 = _mm_set_epi64x(m1, m12); b1 = _mm_set_epi64x(m4, m14) 44 | #define LOAD_MSG_6_2(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m10, m13) 45 | #define LOAD_MSG_6_3(b0, b1) b0 = _mm_set_epi64x(m6, m0); b1 = _mm_set_epi64x(m8, m9) 46 | #define LOAD_MSG_6_4(b0, b1) b0 = _mm_set_epi64x(m3, m7); b1 = _mm_set_epi64x(m11, m2) 47 | #define LOAD_MSG_7_1(b0, b1) b0 = _mm_set_epi64x(m7, m13); b1 = _mm_set_epi64x(m3, m12) 48 | #define LOAD_MSG_7_2(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m9, m1) 49 | #define LOAD_MSG_7_3(b0, b1) b0 = _mm_set_epi64x(m15, m5); b1 = _mm_set_epi64x(m2, m8) 50 | #define LOAD_MSG_7_4(b0, b1) b0 = _mm_set_epi64x(m4, m0); b1 = _mm_set_epi64x(m10, m6) 51 | #define LOAD_MSG_8_1(b0, b1) b0 = _mm_set_epi64x(m14, m6); b1 = _mm_set_epi64x(m0, m11) 52 | #define LOAD_MSG_8_2(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m8, m3) 53 | #define LOAD_MSG_8_3(b0, b1) b0 = _mm_set_epi64x(m13, m12); b1 = _mm_set_epi64x(m10, m1) 54 | #define LOAD_MSG_8_4(b0, b1) b0 = _mm_set_epi64x(m7, m2); b1 = _mm_set_epi64x(m5, m4) 55 | #define LOAD_MSG_9_1(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m1, m7) 56 | #define LOAD_MSG_9_2(b0, b1) b0 = _mm_set_epi64x(m4, m2); b1 = _mm_set_epi64x(m5, m6) 57 | #define LOAD_MSG_9_3(b0, b1) b0 = _mm_set_epi64x(m9, m15); b1 = _mm_set_epi64x(m13, m3) 58 | #define LOAD_MSG_9_4(b0, b1) b0 = _mm_set_epi64x(m14, m11); b1 = _mm_set_epi64x(m0, m12) 59 | #define LOAD_MSG_10_1(b0, b1) b0 = _mm_set_epi64x(m2, m0); b1 = _mm_set_epi64x(m6, m4) 60 | #define LOAD_MSG_10_2(b0, b1) b0 = _mm_set_epi64x(m3, m1); b1 = _mm_set_epi64x(m7, m5) 61 | #define LOAD_MSG_10_3(b0, b1) b0 = _mm_set_epi64x(m10, m8); b1 = _mm_set_epi64x(m14, m12) 62 | #define LOAD_MSG_10_4(b0, b1) b0 = _mm_set_epi64x(m11, m9); b1 = _mm_set_epi64x(m15, m13) 63 | #define LOAD_MSG_11_1(b0, b1) b0 = _mm_set_epi64x(m4, m14); b1 = _mm_set_epi64x(m13, m9) 64 | #define LOAD_MSG_11_2(b0, b1) b0 = _mm_set_epi64x(m8, m10); b1 = _mm_set_epi64x(m6, m15) 65 | #define LOAD_MSG_11_3(b0, b1) b0 = _mm_set_epi64x(m0, m1); b1 = _mm_set_epi64x(m5, m11) 66 | #define LOAD_MSG_11_4(b0, b1) b0 = _mm_set_epi64x(m2, m12); b1 = _mm_set_epi64x(m3, m7) 67 | 68 | 69 | #endif 70 | 71 | -------------------------------------------------------------------------------- /impl/blake2b-load-sse41.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2B_LOAD_SSE41_H__ 17 | #define __BLAKE2B_LOAD_SSE41_H__ 18 | 19 | #define LOAD_MSG_0_1(b0, b1) \ 20 | do \ 21 | { \ 22 | b0 = _mm_unpacklo_epi64(m0, m1); \ 23 | b1 = _mm_unpacklo_epi64(m2, m3); \ 24 | } while(0) 25 | 26 | 27 | #define LOAD_MSG_0_2(b0, b1) \ 28 | do \ 29 | { \ 30 | b0 = _mm_unpackhi_epi64(m0, m1); \ 31 | b1 = _mm_unpackhi_epi64(m2, m3); \ 32 | } while(0) 33 | 34 | 35 | #define LOAD_MSG_0_3(b0, b1) \ 36 | do \ 37 | { \ 38 | b0 = _mm_unpacklo_epi64(m4, m5); \ 39 | b1 = _mm_unpacklo_epi64(m6, m7); \ 40 | } while(0) 41 | 42 | 43 | #define LOAD_MSG_0_4(b0, b1) \ 44 | do \ 45 | { \ 46 | b0 = _mm_unpackhi_epi64(m4, m5); \ 47 | b1 = _mm_unpackhi_epi64(m6, m7); \ 48 | } while(0) 49 | 50 | 51 | #define LOAD_MSG_1_1(b0, b1) \ 52 | do \ 53 | { \ 54 | b0 = _mm_unpacklo_epi64(m7, m2); \ 55 | b1 = _mm_unpackhi_epi64(m4, m6); \ 56 | } while(0) 57 | 58 | 59 | #define LOAD_MSG_1_2(b0, b1) \ 60 | do \ 61 | { \ 62 | b0 = _mm_unpacklo_epi64(m5, m4); \ 63 | b1 = _mm_alignr_epi8(m3, m7, 8); \ 64 | } while(0) 65 | 66 | 67 | #define LOAD_MSG_1_3(b0, b1) \ 68 | do \ 69 | { \ 70 | b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \ 71 | b1 = _mm_unpackhi_epi64(m5, m2); \ 72 | } while(0) 73 | 74 | 75 | #define LOAD_MSG_1_4(b0, b1) \ 76 | do \ 77 | { \ 78 | b0 = _mm_unpacklo_epi64(m6, m1); \ 79 | b1 = _mm_unpackhi_epi64(m3, m1); \ 80 | } while(0) 81 | 82 | 83 | #define LOAD_MSG_2_1(b0, b1) \ 84 | do \ 85 | { \ 86 | b0 = _mm_alignr_epi8(m6, m5, 8); \ 87 | b1 = _mm_unpackhi_epi64(m2, m7); \ 88 | } while(0) 89 | 90 | 91 | #define LOAD_MSG_2_2(b0, b1) \ 92 | do \ 93 | { \ 94 | b0 = _mm_unpacklo_epi64(m4, m0); \ 95 | b1 = _mm_blend_epi16(m1, m6, 0xF0); \ 96 | } while(0) 97 | 98 | 99 | #define LOAD_MSG_2_3(b0, b1) \ 100 | do \ 101 | { \ 102 | b0 = _mm_blend_epi16(m5, m1, 0xF0); \ 103 | b1 = _mm_unpackhi_epi64(m3, m4); \ 104 | } while(0) 105 | 106 | 107 | #define LOAD_MSG_2_4(b0, b1) \ 108 | do \ 109 | { \ 110 | b0 = _mm_unpacklo_epi64(m7, m3); \ 111 | b1 = _mm_alignr_epi8(m2, m0, 8); \ 112 | } while(0) 113 | 114 | 115 | #define LOAD_MSG_3_1(b0, b1) \ 116 | do \ 117 | { \ 118 | b0 = _mm_unpackhi_epi64(m3, m1); \ 119 | b1 = _mm_unpackhi_epi64(m6, m5); \ 120 | } while(0) 121 | 122 | 123 | #define LOAD_MSG_3_2(b0, b1) \ 124 | do \ 125 | { \ 126 | b0 = _mm_unpackhi_epi64(m4, m0); \ 127 | b1 = _mm_unpacklo_epi64(m6, m7); \ 128 | } while(0) 129 | 130 | 131 | #define LOAD_MSG_3_3(b0, b1) \ 132 | do \ 133 | { \ 134 | b0 = _mm_blend_epi16(m1, m2, 0xF0); \ 135 | b1 = _mm_blend_epi16(m2, m7, 0xF0); \ 136 | } while(0) 137 | 138 | 139 | #define LOAD_MSG_3_4(b0, b1) \ 140 | do \ 141 | { \ 142 | b0 = _mm_unpacklo_epi64(m3, m5); \ 143 | b1 = _mm_unpacklo_epi64(m0, m4); \ 144 | } while(0) 145 | 146 | 147 | #define LOAD_MSG_4_1(b0, b1) \ 148 | do \ 149 | { \ 150 | b0 = _mm_unpackhi_epi64(m4, m2); \ 151 | b1 = _mm_unpacklo_epi64(m1, m5); \ 152 | } while(0) 153 | 154 | 155 | #define LOAD_MSG_4_2(b0, b1) \ 156 | do \ 157 | { \ 158 | b0 = _mm_blend_epi16(m0, m3, 0xF0); \ 159 | b1 = _mm_blend_epi16(m2, m7, 0xF0); \ 160 | } while(0) 161 | 162 | 163 | #define LOAD_MSG_4_3(b0, b1) \ 164 | do \ 165 | { \ 166 | b0 = _mm_blend_epi16(m7, m5, 0xF0); \ 167 | b1 = _mm_blend_epi16(m3, m1, 0xF0); \ 168 | } while(0) 169 | 170 | 171 | #define LOAD_MSG_4_4(b0, b1) \ 172 | do \ 173 | { \ 174 | b0 = _mm_alignr_epi8(m6, m0, 8); \ 175 | b1 = _mm_blend_epi16(m4, m6, 0xF0); \ 176 | } while(0) 177 | 178 | 179 | #define LOAD_MSG_5_1(b0, b1) \ 180 | do \ 181 | { \ 182 | b0 = _mm_unpacklo_epi64(m1, m3); \ 183 | b1 = _mm_unpacklo_epi64(m0, m4); \ 184 | } while(0) 185 | 186 | 187 | #define LOAD_MSG_5_2(b0, b1) \ 188 | do \ 189 | { \ 190 | b0 = _mm_unpacklo_epi64(m6, m5); \ 191 | b1 = _mm_unpackhi_epi64(m5, m1); \ 192 | } while(0) 193 | 194 | 195 | #define LOAD_MSG_5_3(b0, b1) \ 196 | do \ 197 | { \ 198 | b0 = _mm_blend_epi16(m2, m3, 0xF0); \ 199 | b1 = _mm_unpackhi_epi64(m7, m0); \ 200 | } while(0) 201 | 202 | 203 | #define LOAD_MSG_5_4(b0, b1) \ 204 | do \ 205 | { \ 206 | b0 = _mm_unpackhi_epi64(m6, m2); \ 207 | b1 = _mm_blend_epi16(m7, m4, 0xF0); \ 208 | } while(0) 209 | 210 | 211 | #define LOAD_MSG_6_1(b0, b1) \ 212 | do \ 213 | { \ 214 | b0 = _mm_blend_epi16(m6, m0, 0xF0); \ 215 | b1 = _mm_unpacklo_epi64(m7, m2); \ 216 | } while(0) 217 | 218 | 219 | #define LOAD_MSG_6_2(b0, b1) \ 220 | do \ 221 | { \ 222 | b0 = _mm_unpackhi_epi64(m2, m7); \ 223 | b1 = _mm_alignr_epi8(m5, m6, 8); \ 224 | } while(0) 225 | 226 | 227 | #define LOAD_MSG_6_3(b0, b1) \ 228 | do \ 229 | { \ 230 | b0 = _mm_unpacklo_epi64(m0, m3); \ 231 | b1 = _mm_shuffle_epi32(m4, _MM_SHUFFLE(1,0,3,2)); \ 232 | } while(0) 233 | 234 | 235 | #define LOAD_MSG_6_4(b0, b1) \ 236 | do \ 237 | { \ 238 | b0 = _mm_unpackhi_epi64(m3, m1); \ 239 | b1 = _mm_blend_epi16(m1, m5, 0xF0); \ 240 | } while(0) 241 | 242 | 243 | #define LOAD_MSG_7_1(b0, b1) \ 244 | do \ 245 | { \ 246 | b0 = _mm_unpackhi_epi64(m6, m3); \ 247 | b1 = _mm_blend_epi16(m6, m1, 0xF0); \ 248 | } while(0) 249 | 250 | 251 | #define LOAD_MSG_7_2(b0, b1) \ 252 | do \ 253 | { \ 254 | b0 = _mm_alignr_epi8(m7, m5, 8); \ 255 | b1 = _mm_unpackhi_epi64(m0, m4); \ 256 | } while(0) 257 | 258 | 259 | #define LOAD_MSG_7_3(b0, b1) \ 260 | do \ 261 | { \ 262 | b0 = _mm_unpackhi_epi64(m2, m7); \ 263 | b1 = _mm_unpacklo_epi64(m4, m1); \ 264 | } while(0) 265 | 266 | 267 | #define LOAD_MSG_7_4(b0, b1) \ 268 | do \ 269 | { \ 270 | b0 = _mm_unpacklo_epi64(m0, m2); \ 271 | b1 = _mm_unpacklo_epi64(m3, m5); \ 272 | } while(0) 273 | 274 | 275 | #define LOAD_MSG_8_1(b0, b1) \ 276 | do \ 277 | { \ 278 | b0 = _mm_unpacklo_epi64(m3, m7); \ 279 | b1 = _mm_alignr_epi8(m0, m5, 8); \ 280 | } while(0) 281 | 282 | 283 | #define LOAD_MSG_8_2(b0, b1) \ 284 | do \ 285 | { \ 286 | b0 = _mm_unpackhi_epi64(m7, m4); \ 287 | b1 = _mm_alignr_epi8(m4, m1, 8); \ 288 | } while(0) 289 | 290 | 291 | #define LOAD_MSG_8_3(b0, b1) \ 292 | do \ 293 | { \ 294 | b0 = m6; \ 295 | b1 = _mm_alignr_epi8(m5, m0, 8); \ 296 | } while(0) 297 | 298 | 299 | #define LOAD_MSG_8_4(b0, b1) \ 300 | do \ 301 | { \ 302 | b0 = _mm_blend_epi16(m1, m3, 0xF0); \ 303 | b1 = m2; \ 304 | } while(0) 305 | 306 | 307 | #define LOAD_MSG_9_1(b0, b1) \ 308 | do \ 309 | { \ 310 | b0 = _mm_unpacklo_epi64(m5, m4); \ 311 | b1 = _mm_unpackhi_epi64(m3, m0); \ 312 | } while(0) 313 | 314 | 315 | #define LOAD_MSG_9_2(b0, b1) \ 316 | do \ 317 | { \ 318 | b0 = _mm_unpacklo_epi64(m1, m2); \ 319 | b1 = _mm_blend_epi16(m3, m2, 0xF0); \ 320 | } while(0) 321 | 322 | 323 | #define LOAD_MSG_9_3(b0, b1) \ 324 | do \ 325 | { \ 326 | b0 = _mm_unpackhi_epi64(m7, m4); \ 327 | b1 = _mm_unpackhi_epi64(m1, m6); \ 328 | } while(0) 329 | 330 | 331 | #define LOAD_MSG_9_4(b0, b1) \ 332 | do \ 333 | { \ 334 | b0 = _mm_alignr_epi8(m7, m5, 8); \ 335 | b1 = _mm_unpacklo_epi64(m6, m0); \ 336 | } while(0) 337 | 338 | 339 | #define LOAD_MSG_10_1(b0, b1) \ 340 | do \ 341 | { \ 342 | b0 = _mm_unpacklo_epi64(m0, m1); \ 343 | b1 = _mm_unpacklo_epi64(m2, m3); \ 344 | } while(0) 345 | 346 | 347 | #define LOAD_MSG_10_2(b0, b1) \ 348 | do \ 349 | { \ 350 | b0 = _mm_unpackhi_epi64(m0, m1); \ 351 | b1 = _mm_unpackhi_epi64(m2, m3); \ 352 | } while(0) 353 | 354 | 355 | #define LOAD_MSG_10_3(b0, b1) \ 356 | do \ 357 | { \ 358 | b0 = _mm_unpacklo_epi64(m4, m5); \ 359 | b1 = _mm_unpacklo_epi64(m6, m7); \ 360 | } while(0) 361 | 362 | 363 | #define LOAD_MSG_10_4(b0, b1) \ 364 | do \ 365 | { \ 366 | b0 = _mm_unpackhi_epi64(m4, m5); \ 367 | b1 = _mm_unpackhi_epi64(m6, m7); \ 368 | } while(0) 369 | 370 | 371 | #define LOAD_MSG_11_1(b0, b1) \ 372 | do \ 373 | { \ 374 | b0 = _mm_unpacklo_epi64(m7, m2); \ 375 | b1 = _mm_unpackhi_epi64(m4, m6); \ 376 | } while(0) 377 | 378 | 379 | #define LOAD_MSG_11_2(b0, b1) \ 380 | do \ 381 | { \ 382 | b0 = _mm_unpacklo_epi64(m5, m4); \ 383 | b1 = _mm_alignr_epi8(m3, m7, 8); \ 384 | } while(0) 385 | 386 | 387 | #define LOAD_MSG_11_3(b0, b1) \ 388 | do \ 389 | { \ 390 | b0 = _mm_shuffle_epi32(m0, _MM_SHUFFLE(1,0,3,2)); \ 391 | b1 = _mm_unpackhi_epi64(m5, m2); \ 392 | } while(0) 393 | 394 | 395 | #define LOAD_MSG_11_4(b0, b1) \ 396 | do \ 397 | { \ 398 | b0 = _mm_unpacklo_epi64(m6, m1); \ 399 | b1 = _mm_unpackhi_epi64(m3, m1); \ 400 | } while(0) 401 | 402 | 403 | #endif 404 | 405 | -------------------------------------------------------------------------------- /impl/blake2b-ref.c: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "blake2.h" 20 | #include "blake2-impl.h" 21 | 22 | static const uint64_t blake2b_IV[8] = 23 | { 24 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 25 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 26 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 27 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 28 | }; 29 | 30 | static const uint8_t blake2b_sigma[12][16] = 31 | { 32 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 33 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 34 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 35 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 36 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 37 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 38 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 39 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 40 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 41 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 42 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 43 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 44 | }; 45 | 46 | 47 | BLAKE2_LOCAL_INLINE(int) blake2b_set_lastnode( blake2b_state *S ) 48 | { 49 | S->f[1] = -1; 50 | return 0; 51 | } 52 | 53 | BLAKE2_LOCAL_INLINE(int) blake2b_clear_lastnode( blake2b_state *S ) 54 | { 55 | S->f[1] = 0; 56 | return 0; 57 | } 58 | 59 | /* Some helper functions, not necessarily useful */ 60 | BLAKE2_LOCAL_INLINE(int) blake2b_is_lastblock( const blake2b_state *S ) 61 | { 62 | return S->f[0] != 0; 63 | } 64 | 65 | BLAKE2_LOCAL_INLINE(int) blake2b_set_lastblock( blake2b_state *S ) 66 | { 67 | if( S->last_node ) blake2b_set_lastnode( S ); 68 | 69 | S->f[0] = -1; 70 | return 0; 71 | } 72 | 73 | BLAKE2_LOCAL_INLINE(int) blake2b_clear_lastblock( blake2b_state *S ) 74 | { 75 | if( S->last_node ) blake2b_clear_lastnode( S ); 76 | 77 | S->f[0] = 0; 78 | return 0; 79 | } 80 | 81 | BLAKE2_LOCAL_INLINE(int) blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) 82 | { 83 | S->t[0] += inc; 84 | S->t[1] += ( S->t[0] < inc ); 85 | return 0; 86 | } 87 | 88 | 89 | 90 | /* Parameter-related functions */ 91 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length ) 92 | { 93 | P->digest_length = digest_length; 94 | return 0; 95 | } 96 | 97 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout ) 98 | { 99 | P->fanout = fanout; 100 | return 0; 101 | } 102 | 103 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth ) 104 | { 105 | P->depth = depth; 106 | return 0; 107 | } 108 | 109 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length ) 110 | { 111 | store32( &P->leaf_length, leaf_length ); 112 | return 0; 113 | } 114 | 115 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset ) 116 | { 117 | store64( &P->node_offset, node_offset ); 118 | return 0; 119 | } 120 | 121 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth ) 122 | { 123 | P->node_depth = node_depth; 124 | return 0; 125 | } 126 | 127 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length ) 128 | { 129 | P->inner_length = inner_length; 130 | return 0; 131 | } 132 | 133 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] ) 134 | { 135 | memcpy( P->salt, salt, BLAKE2B_SALTBYTES ); 136 | return 0; 137 | } 138 | 139 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] ) 140 | { 141 | memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES ); 142 | return 0; 143 | } 144 | 145 | BLAKE2_LOCAL_INLINE(int) blake2b_init0( blake2b_state *S ) 146 | { 147 | int i; 148 | memset( S, 0, sizeof( blake2b_state ) ); 149 | 150 | for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 151 | 152 | return 0; 153 | } 154 | 155 | /* init xors IV with input parameter block */ 156 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 157 | { 158 | const uint8_t *p = ( const uint8_t * )( P ); 159 | size_t i; 160 | 161 | blake2b_init0( S ); 162 | 163 | /* IV XOR ParamBlock */ 164 | for( i = 0; i < 8; ++i ) 165 | S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); 166 | 167 | return 0; 168 | } 169 | 170 | 171 | 172 | int blake2b_init( blake2b_state *S, const uint8_t outlen ) 173 | { 174 | blake2b_param P[1]; 175 | 176 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 177 | 178 | P->digest_length = outlen; 179 | P->key_length = 0; 180 | P->fanout = 1; 181 | P->depth = 1; 182 | store32( &P->leaf_length, 0 ); 183 | store64( &P->node_offset, 0 ); 184 | P->node_depth = 0; 185 | P->inner_length = 0; 186 | memset( P->reserved, 0, sizeof( P->reserved ) ); 187 | memset( P->salt, 0, sizeof( P->salt ) ); 188 | memset( P->personal, 0, sizeof( P->personal ) ); 189 | return blake2b_init_param( S, P ); 190 | } 191 | 192 | 193 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 194 | { 195 | blake2b_param P[1]; 196 | 197 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 198 | 199 | if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; 200 | 201 | P->digest_length = outlen; 202 | P->key_length = keylen; 203 | P->fanout = 1; 204 | P->depth = 1; 205 | store32( &P->leaf_length, 0 ); 206 | store64( &P->node_offset, 0 ); 207 | P->node_depth = 0; 208 | P->inner_length = 0; 209 | memset( P->reserved, 0, sizeof( P->reserved ) ); 210 | memset( P->salt, 0, sizeof( P->salt ) ); 211 | memset( P->personal, 0, sizeof( P->personal ) ); 212 | 213 | if( blake2b_init_param( S, P ) < 0 ) return -1; 214 | 215 | { 216 | uint8_t block[BLAKE2B_BLOCKBYTES]; 217 | memset( block, 0, BLAKE2B_BLOCKBYTES ); 218 | memcpy( block, key, keylen ); 219 | blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 220 | secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 221 | } 222 | return 0; 223 | } 224 | 225 | static int blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) 226 | { 227 | uint64_t m[16]; 228 | uint64_t v[16]; 229 | int i; 230 | 231 | for( i = 0; i < 16; ++i ) 232 | m[i] = load64( block + i * sizeof( m[i] ) ); 233 | 234 | for( i = 0; i < 8; ++i ) 235 | v[i] = S->h[i]; 236 | 237 | v[ 8] = blake2b_IV[0]; 238 | v[ 9] = blake2b_IV[1]; 239 | v[10] = blake2b_IV[2]; 240 | v[11] = blake2b_IV[3]; 241 | v[12] = S->t[0] ^ blake2b_IV[4]; 242 | v[13] = S->t[1] ^ blake2b_IV[5]; 243 | v[14] = S->f[0] ^ blake2b_IV[6]; 244 | v[15] = S->f[1] ^ blake2b_IV[7]; 245 | #define G(r,i,a,b,c,d) \ 246 | do { \ 247 | a = a + b + m[blake2b_sigma[r][2*i+0]]; \ 248 | d = rotr64(d ^ a, 32); \ 249 | c = c + d; \ 250 | b = rotr64(b ^ c, 24); \ 251 | a = a + b + m[blake2b_sigma[r][2*i+1]]; \ 252 | d = rotr64(d ^ a, 16); \ 253 | c = c + d; \ 254 | b = rotr64(b ^ c, 63); \ 255 | } while(0) 256 | #define ROUND(r) \ 257 | do { \ 258 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 259 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 260 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 261 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 262 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 263 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 264 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 265 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 266 | } while(0) 267 | ROUND( 0 ); 268 | ROUND( 1 ); 269 | ROUND( 2 ); 270 | ROUND( 3 ); 271 | ROUND( 4 ); 272 | ROUND( 5 ); 273 | ROUND( 6 ); 274 | ROUND( 7 ); 275 | ROUND( 8 ); 276 | ROUND( 9 ); 277 | ROUND( 10 ); 278 | ROUND( 11 ); 279 | 280 | for( i = 0; i < 8; ++i ) 281 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 282 | 283 | #undef G 284 | #undef ROUND 285 | return 0; 286 | } 287 | 288 | /* inlen now in bytes */ 289 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ) 290 | { 291 | while( inlen > 0 ) 292 | { 293 | size_t left = S->buflen; 294 | size_t fill = 2 * BLAKE2B_BLOCKBYTES - left; 295 | 296 | if( inlen > fill ) 297 | { 298 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ 299 | S->buflen += fill; 300 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 301 | blake2b_compress( S, S->buf ); /* Compress */ 302 | memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */ 303 | S->buflen -= BLAKE2B_BLOCKBYTES; 304 | in += fill; 305 | inlen -= fill; 306 | } 307 | else /* inlen <= fill */ 308 | { 309 | memcpy( S->buf + left, in, (size_t)inlen ); 310 | S->buflen += (size_t)inlen; /* Be lazy, do not compress */ 311 | in += inlen; 312 | inlen -= inlen; 313 | } 314 | } 315 | 316 | return 0; 317 | } 318 | 319 | /* Is this correct? */ 320 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ) 321 | { 322 | uint8_t buffer[BLAKE2B_OUTBYTES] = {0}; 323 | int i; 324 | 325 | if( out == NULL || outlen == 0 || outlen > BLAKE2B_OUTBYTES ) 326 | return -1; 327 | 328 | if( blake2b_is_lastblock( S ) ) 329 | return -1; 330 | 331 | if( S->buflen > BLAKE2B_BLOCKBYTES ) 332 | { 333 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 334 | blake2b_compress( S, S->buf ); 335 | S->buflen -= BLAKE2B_BLOCKBYTES; 336 | memmove( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen ); 337 | } 338 | 339 | blake2b_increment_counter( S, S->buflen ); 340 | blake2b_set_lastblock( S ); 341 | memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ 342 | blake2b_compress( S, S->buf ); 343 | 344 | for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 345 | store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 346 | 347 | memcpy( out, buffer, outlen ); 348 | return 0; 349 | } 350 | 351 | /* inlen, at least, should be uint64_t. Others can be size_t. */ 352 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 353 | { 354 | blake2b_state S[1]; 355 | 356 | /* Verify parameters */ 357 | if ( NULL == in && inlen > 0 ) return -1; 358 | 359 | if ( NULL == out ) return -1; 360 | 361 | if( NULL == key && keylen > 0 ) return -1; 362 | 363 | if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; 364 | 365 | if( keylen > BLAKE2B_KEYBYTES ) return -1; 366 | 367 | if( keylen > 0 ) 368 | { 369 | if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 370 | } 371 | else 372 | { 373 | if( blake2b_init( S, outlen ) < 0 ) return -1; 374 | } 375 | 376 | blake2b_update( S, ( const uint8_t * )in, inlen ); 377 | blake2b_final( S, out, outlen ); 378 | return 0; 379 | } 380 | 381 | #if defined(SUPERCOP) 382 | int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) 383 | { 384 | return blake2b( out, in, NULL, BLAKE2B_OUTBYTES, inlen, 0 ); 385 | } 386 | #endif 387 | 388 | #if defined(BLAKE2B_SELFTEST) 389 | #include 390 | #include "blake2-kat.h" 391 | int main( int argc, char **argv ) 392 | { 393 | uint8_t key[BLAKE2B_KEYBYTES]; 394 | uint8_t buf[KAT_LENGTH]; 395 | size_t i; 396 | 397 | for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) 398 | key[i] = ( uint8_t )i; 399 | 400 | for( i = 0; i < KAT_LENGTH; ++i ) 401 | buf[i] = ( uint8_t )i; 402 | 403 | for( i = 0; i < KAT_LENGTH; ++i ) 404 | { 405 | uint8_t hash[BLAKE2B_OUTBYTES]; 406 | blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 407 | 408 | if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 409 | { 410 | puts( "error" ); 411 | return -1; 412 | } 413 | } 414 | 415 | puts( "ok" ); 416 | return 0; 417 | } 418 | #endif 419 | 420 | -------------------------------------------------------------------------------- /impl/blake2b-round.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2B_ROUND_H__ 17 | #define __BLAKE2B_ROUND_H__ 18 | 19 | #define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) ) 20 | #define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r) 21 | 22 | #define TOF(reg) _mm_castsi128_ps((reg)) 23 | #define TOI(reg) _mm_castps_si128((reg)) 24 | 25 | #define LIKELY(x) __builtin_expect((x),1) 26 | 27 | 28 | /* Microarchitecture-specific macros */ 29 | #ifndef HAVE_XOP 30 | #ifdef HAVE_SSSE3 31 | #define _mm_roti_epi64(x, c) \ 32 | (-(c) == 32) ? _mm_shuffle_epi32((x), _MM_SHUFFLE(2,3,0,1)) \ 33 | : (-(c) == 24) ? _mm_shuffle_epi8((x), r24) \ 34 | : (-(c) == 16) ? _mm_shuffle_epi8((x), r16) \ 35 | : (-(c) == 63) ? _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_add_epi64((x), (x))) \ 36 | : _mm_xor_si128(_mm_srli_epi64((x), -(c)), _mm_slli_epi64((x), 64-(-(c)))) 37 | #else 38 | #define _mm_roti_epi64(r, c) _mm_xor_si128(_mm_srli_epi64( (r), -(c) ),_mm_slli_epi64( (r), 64-(-(c)) )) 39 | #endif 40 | #else 41 | /* ... */ 42 | #endif 43 | 44 | 45 | 46 | #define G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 47 | row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ 48 | row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ 49 | \ 50 | row4l = _mm_xor_si128(row4l, row1l); \ 51 | row4h = _mm_xor_si128(row4h, row1h); \ 52 | \ 53 | row4l = _mm_roti_epi64(row4l, -32); \ 54 | row4h = _mm_roti_epi64(row4h, -32); \ 55 | \ 56 | row3l = _mm_add_epi64(row3l, row4l); \ 57 | row3h = _mm_add_epi64(row3h, row4h); \ 58 | \ 59 | row2l = _mm_xor_si128(row2l, row3l); \ 60 | row2h = _mm_xor_si128(row2h, row3h); \ 61 | \ 62 | row2l = _mm_roti_epi64(row2l, -24); \ 63 | row2h = _mm_roti_epi64(row2h, -24); \ 64 | 65 | #define G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1) \ 66 | row1l = _mm_add_epi64(_mm_add_epi64(row1l, b0), row2l); \ 67 | row1h = _mm_add_epi64(_mm_add_epi64(row1h, b1), row2h); \ 68 | \ 69 | row4l = _mm_xor_si128(row4l, row1l); \ 70 | row4h = _mm_xor_si128(row4h, row1h); \ 71 | \ 72 | row4l = _mm_roti_epi64(row4l, -16); \ 73 | row4h = _mm_roti_epi64(row4h, -16); \ 74 | \ 75 | row3l = _mm_add_epi64(row3l, row4l); \ 76 | row3h = _mm_add_epi64(row3h, row4h); \ 77 | \ 78 | row2l = _mm_xor_si128(row2l, row3l); \ 79 | row2h = _mm_xor_si128(row2h, row3h); \ 80 | \ 81 | row2l = _mm_roti_epi64(row2l, -63); \ 82 | row2h = _mm_roti_epi64(row2h, -63); \ 83 | 84 | #if defined(HAVE_SSSE3) 85 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 86 | t0 = _mm_alignr_epi8(row2h, row2l, 8); \ 87 | t1 = _mm_alignr_epi8(row2l, row2h, 8); \ 88 | row2l = t0; \ 89 | row2h = t1; \ 90 | \ 91 | t0 = row3l; \ 92 | row3l = row3h; \ 93 | row3h = t0; \ 94 | \ 95 | t0 = _mm_alignr_epi8(row4h, row4l, 8); \ 96 | t1 = _mm_alignr_epi8(row4l, row4h, 8); \ 97 | row4l = t1; \ 98 | row4h = t0; 99 | 100 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 101 | t0 = _mm_alignr_epi8(row2l, row2h, 8); \ 102 | t1 = _mm_alignr_epi8(row2h, row2l, 8); \ 103 | row2l = t0; \ 104 | row2h = t1; \ 105 | \ 106 | t0 = row3l; \ 107 | row3l = row3h; \ 108 | row3h = t0; \ 109 | \ 110 | t0 = _mm_alignr_epi8(row4l, row4h, 8); \ 111 | t1 = _mm_alignr_epi8(row4h, row4l, 8); \ 112 | row4l = t1; \ 113 | row4h = t0; 114 | #else 115 | 116 | #define DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 117 | t0 = row4l;\ 118 | t1 = row2l;\ 119 | row4l = row3l;\ 120 | row3l = row3h;\ 121 | row3h = row4l;\ 122 | row4l = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t0, t0)); \ 123 | row4h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row4h, row4h)); \ 124 | row2l = _mm_unpackhi_epi64(row2l, _mm_unpacklo_epi64(row2h, row2h)); \ 125 | row2h = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(t1, t1)) 126 | 127 | #define UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h) \ 128 | t0 = row3l;\ 129 | row3l = row3h;\ 130 | row3h = t0;\ 131 | t0 = row2l;\ 132 | t1 = row4l;\ 133 | row2l = _mm_unpackhi_epi64(row2h, _mm_unpacklo_epi64(row2l, row2l)); \ 134 | row2h = _mm_unpackhi_epi64(t0, _mm_unpacklo_epi64(row2h, row2h)); \ 135 | row4l = _mm_unpackhi_epi64(row4l, _mm_unpacklo_epi64(row4h, row4h)); \ 136 | row4h = _mm_unpackhi_epi64(row4h, _mm_unpacklo_epi64(t1, t1)) 137 | 138 | #endif 139 | 140 | #if defined(HAVE_SSE41) 141 | #include "blake2b-load-sse41.h" 142 | #else 143 | #include "blake2b-load-sse2.h" 144 | #endif 145 | 146 | #define ROUND(r) \ 147 | LOAD_MSG_ ##r ##_1(b0, b1); \ 148 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 149 | LOAD_MSG_ ##r ##_2(b0, b1); \ 150 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 151 | DIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); \ 152 | LOAD_MSG_ ##r ##_3(b0, b1); \ 153 | G1(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 154 | LOAD_MSG_ ##r ##_4(b0, b1); \ 155 | G2(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h,b0,b1); \ 156 | UNDIAGONALIZE(row1l,row2l,row3l,row4l,row1h,row2h,row3h,row4h); 157 | 158 | #endif 159 | 160 | -------------------------------------------------------------------------------- /impl/blake2b.c: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "blake2.h" 20 | #include "blake2-impl.h" 21 | 22 | #include "blake2-config.h" 23 | 24 | #ifdef _MSC_VER 25 | #include /* for _mm_set_epi64x */ 26 | #endif 27 | #include 28 | #if defined(HAVE_SSSE3) 29 | #include 30 | #endif 31 | #if defined(HAVE_SSE41) 32 | #include 33 | #endif 34 | #if defined(HAVE_AVX) 35 | #include 36 | #endif 37 | #if defined(HAVE_XOP) 38 | #include 39 | #endif 40 | 41 | #include "blake2b-round.h" 42 | 43 | static const uint64_t blake2b_IV[8] = 44 | { 45 | 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, 46 | 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, 47 | 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, 48 | 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL 49 | }; 50 | 51 | static const uint8_t blake2b_sigma[12][16] = 52 | { 53 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 54 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 55 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 56 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 57 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 58 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 59 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 60 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 61 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 62 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 63 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 64 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } 65 | }; 66 | 67 | 68 | /* Some helper functions, not necessarily useful */ 69 | BLAKE2_LOCAL_INLINE(int) blake2b_set_lastnode( blake2b_state *S ) 70 | { 71 | S->f[1] = -1; 72 | return 0; 73 | } 74 | 75 | BLAKE2_LOCAL_INLINE(int) blake2b_clear_lastnode( blake2b_state *S ) 76 | { 77 | S->f[1] = 0; 78 | return 0; 79 | } 80 | 81 | BLAKE2_LOCAL_INLINE(int) blake2b_is_lastblock( const blake2b_state *S ) 82 | { 83 | return S->f[0] != 0; 84 | } 85 | 86 | BLAKE2_LOCAL_INLINE(int) blake2b_set_lastblock( blake2b_state *S ) 87 | { 88 | if( S->last_node ) blake2b_set_lastnode( S ); 89 | 90 | S->f[0] = -1; 91 | return 0; 92 | } 93 | 94 | BLAKE2_LOCAL_INLINE(int) blake2b_clear_lastblock( blake2b_state *S ) 95 | { 96 | if( S->last_node ) blake2b_clear_lastnode( S ); 97 | 98 | S->f[0] = 0; 99 | return 0; 100 | } 101 | 102 | 103 | BLAKE2_LOCAL_INLINE(int) blake2b_increment_counter( blake2b_state *S, const uint64_t inc ) 104 | { 105 | #if __x86_64__ 106 | /* ADD/ADC chain */ 107 | __uint128_t t = ( ( __uint128_t )S->t[1] << 64 ) | S->t[0]; 108 | t += inc; 109 | S->t[0] = ( uint64_t )( t >> 0 ); 110 | S->t[1] = ( uint64_t )( t >> 64 ); 111 | #else 112 | S->t[0] += inc; 113 | S->t[1] += ( S->t[0] < inc ); 114 | #endif 115 | return 0; 116 | } 117 | 118 | 119 | /* Parameter-related functions */ 120 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_digest_length( blake2b_param *P, const uint8_t digest_length ) 121 | { 122 | P->digest_length = digest_length; 123 | return 0; 124 | } 125 | 126 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_fanout( blake2b_param *P, const uint8_t fanout ) 127 | { 128 | P->fanout = fanout; 129 | return 0; 130 | } 131 | 132 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_max_depth( blake2b_param *P, const uint8_t depth ) 133 | { 134 | P->depth = depth; 135 | return 0; 136 | } 137 | 138 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_leaf_length( blake2b_param *P, const uint32_t leaf_length ) 139 | { 140 | P->leaf_length = leaf_length; 141 | return 0; 142 | } 143 | 144 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_node_offset( blake2b_param *P, const uint64_t node_offset ) 145 | { 146 | P->node_offset = node_offset; 147 | return 0; 148 | } 149 | 150 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_node_depth( blake2b_param *P, const uint8_t node_depth ) 151 | { 152 | P->node_depth = node_depth; 153 | return 0; 154 | } 155 | 156 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_inner_length( blake2b_param *P, const uint8_t inner_length ) 157 | { 158 | P->inner_length = inner_length; 159 | return 0; 160 | } 161 | 162 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_salt( blake2b_param *P, const uint8_t salt[BLAKE2B_SALTBYTES] ) 163 | { 164 | memcpy( P->salt, salt, BLAKE2B_SALTBYTES ); 165 | return 0; 166 | } 167 | 168 | BLAKE2_LOCAL_INLINE(int) blake2b_param_set_personal( blake2b_param *P, const uint8_t personal[BLAKE2B_PERSONALBYTES] ) 169 | { 170 | memcpy( P->personal, personal, BLAKE2B_PERSONALBYTES ); 171 | return 0; 172 | } 173 | 174 | BLAKE2_LOCAL_INLINE(int) blake2b_init0( blake2b_state *S ) 175 | { 176 | int i; 177 | memset( S, 0, sizeof( blake2b_state ) ); 178 | 179 | for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; 180 | 181 | return 0; 182 | } 183 | 184 | /* init xors IV with input parameter block */ 185 | int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) 186 | { 187 | /*blake2b_init0( S ); */ 188 | const uint8_t * v = ( const uint8_t * )( blake2b_IV ); 189 | const uint8_t * p = ( const uint8_t * )( P ); 190 | uint8_t * h = ( uint8_t * )( S->h ); 191 | int i; 192 | /* IV XOR ParamBlock */ 193 | memset( S, 0, sizeof( blake2b_state ) ); 194 | 195 | for( i = 0; i < BLAKE2B_OUTBYTES; ++i ) h[i] = v[i] ^ p[i]; 196 | 197 | return 0; 198 | } 199 | 200 | 201 | /* Some sort of default parameter block initialization, for sequential blake2b */ 202 | int blake2b_init( blake2b_state *S, const uint8_t outlen ) 203 | { 204 | const blake2b_param P = 205 | { 206 | outlen, 207 | 0, 208 | 1, 209 | 1, 210 | 0, 211 | 0, 212 | 0, 213 | 0, 214 | {0}, 215 | {0}, 216 | {0} 217 | }; 218 | 219 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 220 | 221 | return blake2b_init_param( S, &P ); 222 | } 223 | 224 | int blake2b_init_key( blake2b_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 225 | { 226 | const blake2b_param P = 227 | { 228 | outlen, 229 | keylen, 230 | 1, 231 | 1, 232 | 0, 233 | 0, 234 | 0, 235 | 0, 236 | {0}, 237 | {0}, 238 | {0} 239 | }; 240 | 241 | if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; 242 | 243 | if ( ( !keylen ) || keylen > BLAKE2B_KEYBYTES ) return -1; 244 | 245 | if( blake2b_init_param( S, &P ) < 0 ) 246 | return 0; 247 | 248 | { 249 | uint8_t block[BLAKE2B_BLOCKBYTES]; 250 | memset( block, 0, BLAKE2B_BLOCKBYTES ); 251 | memcpy( block, key, keylen ); 252 | blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); 253 | secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from stack */ 254 | } 255 | return 0; 256 | } 257 | 258 | BLAKE2_LOCAL_INLINE(int) blake2b_compress( blake2b_state *S, const uint8_t block[BLAKE2B_BLOCKBYTES] ) 259 | { 260 | __m128i row1l, row1h; 261 | __m128i row2l, row2h; 262 | __m128i row3l, row3h; 263 | __m128i row4l, row4h; 264 | __m128i b0, b1; 265 | __m128i t0, t1; 266 | #if defined(HAVE_SSSE3) && !defined(HAVE_XOP) 267 | const __m128i r16 = _mm_setr_epi8( 2, 3, 4, 5, 6, 7, 0, 1, 10, 11, 12, 13, 14, 15, 8, 9 ); 268 | const __m128i r24 = _mm_setr_epi8( 3, 4, 5, 6, 7, 0, 1, 2, 11, 12, 13, 14, 15, 8, 9, 10 ); 269 | #endif 270 | #if defined(HAVE_SSE41) 271 | const __m128i m0 = LOADU( block + 00 ); 272 | const __m128i m1 = LOADU( block + 16 ); 273 | const __m128i m2 = LOADU( block + 32 ); 274 | const __m128i m3 = LOADU( block + 48 ); 275 | const __m128i m4 = LOADU( block + 64 ); 276 | const __m128i m5 = LOADU( block + 80 ); 277 | const __m128i m6 = LOADU( block + 96 ); 278 | const __m128i m7 = LOADU( block + 112 ); 279 | #else 280 | const uint64_t m0 = ( ( uint64_t * )block )[ 0]; 281 | const uint64_t m1 = ( ( uint64_t * )block )[ 1]; 282 | const uint64_t m2 = ( ( uint64_t * )block )[ 2]; 283 | const uint64_t m3 = ( ( uint64_t * )block )[ 3]; 284 | const uint64_t m4 = ( ( uint64_t * )block )[ 4]; 285 | const uint64_t m5 = ( ( uint64_t * )block )[ 5]; 286 | const uint64_t m6 = ( ( uint64_t * )block )[ 6]; 287 | const uint64_t m7 = ( ( uint64_t * )block )[ 7]; 288 | const uint64_t m8 = ( ( uint64_t * )block )[ 8]; 289 | const uint64_t m9 = ( ( uint64_t * )block )[ 9]; 290 | const uint64_t m10 = ( ( uint64_t * )block )[10]; 291 | const uint64_t m11 = ( ( uint64_t * )block )[11]; 292 | const uint64_t m12 = ( ( uint64_t * )block )[12]; 293 | const uint64_t m13 = ( ( uint64_t * )block )[13]; 294 | const uint64_t m14 = ( ( uint64_t * )block )[14]; 295 | const uint64_t m15 = ( ( uint64_t * )block )[15]; 296 | #endif 297 | row1l = LOADU( &S->h[0] ); 298 | row1h = LOADU( &S->h[2] ); 299 | row2l = LOADU( &S->h[4] ); 300 | row2h = LOADU( &S->h[6] ); 301 | row3l = LOADU( &blake2b_IV[0] ); 302 | row3h = LOADU( &blake2b_IV[2] ); 303 | row4l = _mm_xor_si128( LOADU( &blake2b_IV[4] ), LOADU( &S->t[0] ) ); 304 | row4h = _mm_xor_si128( LOADU( &blake2b_IV[6] ), LOADU( &S->f[0] ) ); 305 | ROUND( 0 ); 306 | ROUND( 1 ); 307 | ROUND( 2 ); 308 | ROUND( 3 ); 309 | ROUND( 4 ); 310 | ROUND( 5 ); 311 | ROUND( 6 ); 312 | ROUND( 7 ); 313 | ROUND( 8 ); 314 | ROUND( 9 ); 315 | ROUND( 10 ); 316 | ROUND( 11 ); 317 | row1l = _mm_xor_si128( row3l, row1l ); 318 | row1h = _mm_xor_si128( row3h, row1h ); 319 | STOREU( &S->h[0], _mm_xor_si128( LOADU( &S->h[0] ), row1l ) ); 320 | STOREU( &S->h[2], _mm_xor_si128( LOADU( &S->h[2] ), row1h ) ); 321 | row2l = _mm_xor_si128( row4l, row2l ); 322 | row2h = _mm_xor_si128( row4h, row2h ); 323 | STOREU( &S->h[4], _mm_xor_si128( LOADU( &S->h[4] ), row2l ) ); 324 | STOREU( &S->h[6], _mm_xor_si128( LOADU( &S->h[6] ), row2h ) ); 325 | return 0; 326 | } 327 | 328 | 329 | int blake2b_update( blake2b_state *S, const uint8_t *in, uint64_t inlen ) 330 | { 331 | while( inlen > 0 ) 332 | { 333 | size_t left = S->buflen; 334 | size_t fill = 2 * BLAKE2B_BLOCKBYTES - left; 335 | 336 | if( inlen > fill ) 337 | { 338 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ 339 | S->buflen += fill; 340 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 341 | blake2b_compress( S, S->buf ); /* Compress */ 342 | memcpy( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); /* Shift buffer left */ 343 | S->buflen -= BLAKE2B_BLOCKBYTES; 344 | in += fill; 345 | inlen -= fill; 346 | } 347 | else /* inlen <= fill */ 348 | { 349 | memcpy( S->buf + left, in, inlen ); 350 | S->buflen += inlen; /* Be lazy, do not compress */ 351 | in += inlen; 352 | inlen -= inlen; 353 | } 354 | } 355 | 356 | return 0; 357 | } 358 | 359 | 360 | int blake2b_final( blake2b_state *S, uint8_t *out, uint8_t outlen ) 361 | { 362 | if( outlen > BLAKE2B_OUTBYTES ) 363 | return -1; 364 | 365 | if( blake2b_is_lastblock( S ) ) 366 | return -1; 367 | 368 | if( S->buflen > BLAKE2B_BLOCKBYTES ) 369 | { 370 | blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); 371 | blake2b_compress( S, S->buf ); 372 | S->buflen -= BLAKE2B_BLOCKBYTES; 373 | memmove( S->buf, S->buf + BLAKE2B_BLOCKBYTES, S->buflen ); 374 | } 375 | 376 | blake2b_increment_counter( S, S->buflen ); 377 | blake2b_set_lastblock( S ); 378 | memset( S->buf + S->buflen, 0, 2 * BLAKE2B_BLOCKBYTES - S->buflen ); /* Padding */ 379 | blake2b_compress( S, S->buf ); 380 | memcpy( out, &S->h[0], outlen ); 381 | return 0; 382 | } 383 | 384 | 385 | int blake2b( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 386 | { 387 | blake2b_state S[1]; 388 | 389 | /* Verify parameters */ 390 | if ( NULL == in && inlen > 0 ) return -1; 391 | 392 | if ( NULL == out ) return -1; 393 | 394 | if( NULL == key && keylen > 0 ) return -1; 395 | 396 | if( !outlen || outlen > BLAKE2B_OUTBYTES ) return -1; 397 | 398 | if( keylen > BLAKE2B_KEYBYTES ) return -1; 399 | 400 | if( keylen ) 401 | { 402 | if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; 403 | } 404 | else 405 | { 406 | if( blake2b_init( S, outlen ) < 0 ) return -1; 407 | } 408 | 409 | blake2b_update( S, ( const uint8_t * )in, inlen ); 410 | blake2b_final( S, out, outlen ); 411 | return 0; 412 | } 413 | 414 | #if defined(SUPERCOP) 415 | int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) 416 | { 417 | return blake2b( out, in, NULL, BLAKE2B_OUTBYTES, inlen, 0 ); 418 | } 419 | #endif 420 | 421 | #if defined(BLAKE2B_SELFTEST) 422 | #include 423 | #include "blake2-kat.h" 424 | int main( int argc, char **argv ) 425 | { 426 | uint8_t key[BLAKE2B_KEYBYTES]; 427 | uint8_t buf[KAT_LENGTH]; 428 | size_t i; 429 | 430 | for( i = 0; i < BLAKE2B_KEYBYTES; ++i ) 431 | key[i] = ( uint8_t )i; 432 | 433 | for( i = 0; i < KAT_LENGTH; ++i ) 434 | buf[i] = ( uint8_t )i; 435 | 436 | for( i = 0; i < KAT_LENGTH; ++i ) 437 | { 438 | uint8_t hash[BLAKE2B_OUTBYTES]; 439 | blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ); 440 | 441 | if( 0 != memcmp( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) 442 | { 443 | puts( "error" ); 444 | return -1; 445 | } 446 | } 447 | 448 | puts( "ok" ); 449 | return 0; 450 | } 451 | #endif 452 | 453 | -------------------------------------------------------------------------------- /impl/blake2s-load-sse2.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2S_LOAD_SSE2_H__ 17 | #define __BLAKE2S_LOAD_SSE2_H__ 18 | 19 | #define LOAD_MSG_0_1(buf) buf = _mm_set_epi32(m6,m4,m2,m0) 20 | #define LOAD_MSG_0_2(buf) buf = _mm_set_epi32(m7,m5,m3,m1) 21 | #define LOAD_MSG_0_3(buf) buf = _mm_set_epi32(m14,m12,m10,m8) 22 | #define LOAD_MSG_0_4(buf) buf = _mm_set_epi32(m15,m13,m11,m9) 23 | #define LOAD_MSG_1_1(buf) buf = _mm_set_epi32(m13,m9,m4,m14) 24 | #define LOAD_MSG_1_2(buf) buf = _mm_set_epi32(m6,m15,m8,m10) 25 | #define LOAD_MSG_1_3(buf) buf = _mm_set_epi32(m5,m11,m0,m1) 26 | #define LOAD_MSG_1_4(buf) buf = _mm_set_epi32(m3,m7,m2,m12) 27 | #define LOAD_MSG_2_1(buf) buf = _mm_set_epi32(m15,m5,m12,m11) 28 | #define LOAD_MSG_2_2(buf) buf = _mm_set_epi32(m13,m2,m0,m8) 29 | #define LOAD_MSG_2_3(buf) buf = _mm_set_epi32(m9,m7,m3,m10) 30 | #define LOAD_MSG_2_4(buf) buf = _mm_set_epi32(m4,m1,m6,m14) 31 | #define LOAD_MSG_3_1(buf) buf = _mm_set_epi32(m11,m13,m3,m7) 32 | #define LOAD_MSG_3_2(buf) buf = _mm_set_epi32(m14,m12,m1,m9) 33 | #define LOAD_MSG_3_3(buf) buf = _mm_set_epi32(m15,m4,m5,m2) 34 | #define LOAD_MSG_3_4(buf) buf = _mm_set_epi32(m8,m0,m10,m6) 35 | #define LOAD_MSG_4_1(buf) buf = _mm_set_epi32(m10,m2,m5,m9) 36 | #define LOAD_MSG_4_2(buf) buf = _mm_set_epi32(m15,m4,m7,m0) 37 | #define LOAD_MSG_4_3(buf) buf = _mm_set_epi32(m3,m6,m11,m14) 38 | #define LOAD_MSG_4_4(buf) buf = _mm_set_epi32(m13,m8,m12,m1) 39 | #define LOAD_MSG_5_1(buf) buf = _mm_set_epi32(m8,m0,m6,m2) 40 | #define LOAD_MSG_5_2(buf) buf = _mm_set_epi32(m3,m11,m10,m12) 41 | #define LOAD_MSG_5_3(buf) buf = _mm_set_epi32(m1,m15,m7,m4) 42 | #define LOAD_MSG_5_4(buf) buf = _mm_set_epi32(m9,m14,m5,m13) 43 | #define LOAD_MSG_6_1(buf) buf = _mm_set_epi32(m4,m14,m1,m12) 44 | #define LOAD_MSG_6_2(buf) buf = _mm_set_epi32(m10,m13,m15,m5) 45 | #define LOAD_MSG_6_3(buf) buf = _mm_set_epi32(m8,m9,m6,m0) 46 | #define LOAD_MSG_6_4(buf) buf = _mm_set_epi32(m11,m2,m3,m7) 47 | #define LOAD_MSG_7_1(buf) buf = _mm_set_epi32(m3,m12,m7,m13) 48 | #define LOAD_MSG_7_2(buf) buf = _mm_set_epi32(m9,m1,m14,m11) 49 | #define LOAD_MSG_7_3(buf) buf = _mm_set_epi32(m2,m8,m15,m5) 50 | #define LOAD_MSG_7_4(buf) buf = _mm_set_epi32(m10,m6,m4,m0) 51 | #define LOAD_MSG_8_1(buf) buf = _mm_set_epi32(m0,m11,m14,m6) 52 | #define LOAD_MSG_8_2(buf) buf = _mm_set_epi32(m8,m3,m9,m15) 53 | #define LOAD_MSG_8_3(buf) buf = _mm_set_epi32(m10,m1,m13,m12) 54 | #define LOAD_MSG_8_4(buf) buf = _mm_set_epi32(m5,m4,m7,m2) 55 | #define LOAD_MSG_9_1(buf) buf = _mm_set_epi32(m1,m7,m8,m10) 56 | #define LOAD_MSG_9_2(buf) buf = _mm_set_epi32(m5,m6,m4,m2) 57 | #define LOAD_MSG_9_3(buf) buf = _mm_set_epi32(m13,m3,m9,m15) 58 | #define LOAD_MSG_9_4(buf) buf = _mm_set_epi32(m0,m12,m14,m11) 59 | 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /impl/blake2s-load-sse41.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2S_LOAD_SSE41_H__ 17 | #define __BLAKE2S_LOAD_SSE41_H__ 18 | 19 | #define LOAD_MSG_0_1(buf) \ 20 | buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(2,0,2,0))); 21 | 22 | #define LOAD_MSG_0_2(buf) \ 23 | buf = TOI(_mm_shuffle_ps(TOF(m0), TOF(m1), _MM_SHUFFLE(3,1,3,1))); 24 | 25 | #define LOAD_MSG_0_3(buf) \ 26 | buf = TOI(_mm_shuffle_ps(TOF(m2), TOF(m3), _MM_SHUFFLE(2,0,2,0))); 27 | 28 | #define LOAD_MSG_0_4(buf) \ 29 | buf = TOI(_mm_shuffle_ps(TOF(m2), TOF(m3), _MM_SHUFFLE(3,1,3,1))); 30 | 31 | #define LOAD_MSG_1_1(buf) \ 32 | t0 = _mm_blend_epi16(m1, m2, 0x0C); \ 33 | t1 = _mm_slli_si128(m3, 4); \ 34 | t2 = _mm_blend_epi16(t0, t1, 0xF0); \ 35 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,0,3)); 36 | 37 | #define LOAD_MSG_1_2(buf) \ 38 | t0 = _mm_shuffle_epi32(m2,_MM_SHUFFLE(0,0,2,0)); \ 39 | t1 = _mm_blend_epi16(m1,m3,0xC0); \ 40 | t2 = _mm_blend_epi16(t0, t1, 0xF0); \ 41 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1)); 42 | 43 | #define LOAD_MSG_1_3(buf) \ 44 | t0 = _mm_slli_si128(m1, 4); \ 45 | t1 = _mm_blend_epi16(m2, t0, 0x30); \ 46 | t2 = _mm_blend_epi16(m0, t1, 0xF0); \ 47 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1)); 48 | 49 | #define LOAD_MSG_1_4(buf) \ 50 | t0 = _mm_unpackhi_epi32(m0,m1); \ 51 | t1 = _mm_slli_si128(m3, 4); \ 52 | t2 = _mm_blend_epi16(t0, t1, 0x0C); \ 53 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,3,0,1)); 54 | 55 | #define LOAD_MSG_2_1(buf) \ 56 | t0 = _mm_unpackhi_epi32(m2,m3); \ 57 | t1 = _mm_blend_epi16(m3,m1,0x0C); \ 58 | t2 = _mm_blend_epi16(t0, t1, 0x0F); \ 59 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2)); 60 | 61 | #define LOAD_MSG_2_2(buf) \ 62 | t0 = _mm_unpacklo_epi32(m2,m0); \ 63 | t1 = _mm_blend_epi16(t0, m0, 0xF0); \ 64 | t2 = _mm_slli_si128(m3, 8); \ 65 | buf = _mm_blend_epi16(t1, t2, 0xC0); 66 | 67 | #define LOAD_MSG_2_3(buf) \ 68 | t0 = _mm_blend_epi16(m0, m2, 0x3C); \ 69 | t1 = _mm_srli_si128(m1, 12); \ 70 | t2 = _mm_blend_epi16(t0,t1,0x03); \ 71 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,0,3,2)); 72 | 73 | #define LOAD_MSG_2_4(buf) \ 74 | t0 = _mm_slli_si128(m3, 4); \ 75 | t1 = _mm_blend_epi16(m0, m1, 0x33); \ 76 | t2 = _mm_blend_epi16(t1, t0, 0xC0); \ 77 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(0,1,2,3)); 78 | 79 | #define LOAD_MSG_3_1(buf) \ 80 | t0 = _mm_unpackhi_epi32(m0,m1); \ 81 | t1 = _mm_unpackhi_epi32(t0, m2); \ 82 | t2 = _mm_blend_epi16(t1, m3, 0x0C); \ 83 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(3,1,0,2)); 84 | 85 | #define LOAD_MSG_3_2(buf) \ 86 | t0 = _mm_slli_si128(m2, 8); \ 87 | t1 = _mm_blend_epi16(m3,m0,0x0C); \ 88 | t2 = _mm_blend_epi16(t1, t0, 0xC0); \ 89 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3)); 90 | 91 | #define LOAD_MSG_3_3(buf) \ 92 | t0 = _mm_blend_epi16(m0,m1,0x0F); \ 93 | t1 = _mm_blend_epi16(t0, m3, 0xC0); \ 94 | buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(3,0,1,2)); 95 | 96 | #define LOAD_MSG_3_4(buf) \ 97 | t0 = _mm_unpacklo_epi32(m0,m2); \ 98 | t1 = _mm_unpackhi_epi32(m1,m2); \ 99 | buf = _mm_unpacklo_epi64(t1,t0); 100 | 101 | #define LOAD_MSG_4_1(buf) \ 102 | t0 = _mm_unpacklo_epi64(m1,m2); \ 103 | t1 = _mm_unpackhi_epi64(m0,m2); \ 104 | t2 = _mm_blend_epi16(t0,t1,0x33); \ 105 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,0,1,3)); 106 | 107 | #define LOAD_MSG_4_2(buf) \ 108 | t0 = _mm_unpackhi_epi64(m1,m3); \ 109 | t1 = _mm_unpacklo_epi64(m0,m1); \ 110 | buf = _mm_blend_epi16(t0,t1,0x33); 111 | 112 | #define LOAD_MSG_4_3(buf) \ 113 | t0 = _mm_unpackhi_epi64(m3,m1); \ 114 | t1 = _mm_unpackhi_epi64(m2,m0); \ 115 | buf = _mm_blend_epi16(t1,t0,0x33); 116 | 117 | #define LOAD_MSG_4_4(buf) \ 118 | t0 = _mm_blend_epi16(m0,m2,0x03); \ 119 | t1 = _mm_slli_si128(t0, 8); \ 120 | t2 = _mm_blend_epi16(t1,m3,0x0F); \ 121 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,2,0,3)); 122 | 123 | #define LOAD_MSG_5_1(buf) \ 124 | t0 = _mm_unpackhi_epi32(m0,m1); \ 125 | t1 = _mm_unpacklo_epi32(m0,m2); \ 126 | buf = _mm_unpacklo_epi64(t0,t1); 127 | 128 | #define LOAD_MSG_5_2(buf) \ 129 | t0 = _mm_srli_si128(m2, 4); \ 130 | t1 = _mm_blend_epi16(m0,m3,0x03); \ 131 | buf = _mm_blend_epi16(t1,t0,0x3C); 132 | 133 | #define LOAD_MSG_5_3(buf) \ 134 | t0 = _mm_blend_epi16(m1,m0,0x0C); \ 135 | t1 = _mm_srli_si128(m3, 4); \ 136 | t2 = _mm_blend_epi16(t0,t1,0x30); \ 137 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,2,3,0)); 138 | 139 | #define LOAD_MSG_5_4(buf) \ 140 | t0 = _mm_unpacklo_epi64(m1,m2); \ 141 | t1= _mm_shuffle_epi32(m3, _MM_SHUFFLE(0,2,0,1)); \ 142 | buf = _mm_blend_epi16(t0,t1,0x33); 143 | 144 | #define LOAD_MSG_6_1(buf) \ 145 | t0 = _mm_slli_si128(m1, 12); \ 146 | t1 = _mm_blend_epi16(m0,m3,0x33); \ 147 | buf = _mm_blend_epi16(t1,t0,0xC0); 148 | 149 | #define LOAD_MSG_6_2(buf) \ 150 | t0 = _mm_blend_epi16(m3,m2,0x30); \ 151 | t1 = _mm_srli_si128(m1, 4); \ 152 | t2 = _mm_blend_epi16(t0,t1,0x03); \ 153 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(2,1,3,0)); 154 | 155 | #define LOAD_MSG_6_3(buf) \ 156 | t0 = _mm_unpacklo_epi64(m0,m2); \ 157 | t1 = _mm_srli_si128(m1, 4); \ 158 | buf = _mm_shuffle_epi32(_mm_blend_epi16(t0,t1,0x0C), _MM_SHUFFLE(2,3,1,0)); 159 | 160 | #define LOAD_MSG_6_4(buf) \ 161 | t0 = _mm_unpackhi_epi32(m1,m2); \ 162 | t1 = _mm_unpackhi_epi64(m0,t0); \ 163 | buf = _mm_shuffle_epi32(t1, _MM_SHUFFLE(3,0,1,2)); 164 | 165 | #define LOAD_MSG_7_1(buf) \ 166 | t0 = _mm_unpackhi_epi32(m0,m1); \ 167 | t1 = _mm_blend_epi16(t0,m3,0x0F); \ 168 | buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(2,0,3,1)); 169 | 170 | #define LOAD_MSG_7_2(buf) \ 171 | t0 = _mm_blend_epi16(m2,m3,0x30); \ 172 | t1 = _mm_srli_si128(m0,4); \ 173 | t2 = _mm_blend_epi16(t0,t1,0x03); \ 174 | buf = _mm_shuffle_epi32(t2, _MM_SHUFFLE(1,0,2,3)); 175 | 176 | #define LOAD_MSG_7_3(buf) \ 177 | t0 = _mm_unpackhi_epi64(m0,m3); \ 178 | t1 = _mm_unpacklo_epi64(m1,m2); \ 179 | t2 = _mm_blend_epi16(t0,t1,0x3C); \ 180 | buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,2,3,1)); 181 | 182 | #define LOAD_MSG_7_4(buf) \ 183 | t0 = _mm_unpacklo_epi32(m0,m1); \ 184 | t1 = _mm_unpackhi_epi32(m1,m2); \ 185 | buf = _mm_unpacklo_epi64(t0,t1); 186 | 187 | #define LOAD_MSG_8_1(buf) \ 188 | t0 = _mm_unpackhi_epi32(m1,m3); \ 189 | t1 = _mm_unpacklo_epi64(t0,m0); \ 190 | t2 = _mm_blend_epi16(t1,m2,0xC0); \ 191 | buf = _mm_shufflehi_epi16(t2,_MM_SHUFFLE(1,0,3,2)); 192 | 193 | #define LOAD_MSG_8_2(buf) \ 194 | t0 = _mm_unpackhi_epi32(m0,m3); \ 195 | t1 = _mm_blend_epi16(m2,t0,0xF0); \ 196 | buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(0,2,1,3)); 197 | 198 | #define LOAD_MSG_8_3(buf) \ 199 | t0 = _mm_blend_epi16(m2,m0,0x0C); \ 200 | t1 = _mm_slli_si128(t0,4); \ 201 | buf = _mm_blend_epi16(t1,m3,0x0F); 202 | 203 | #define LOAD_MSG_8_4(buf) \ 204 | t0 = _mm_blend_epi16(m1,m0,0x30); \ 205 | buf = _mm_shuffle_epi32(t0,_MM_SHUFFLE(1,0,3,2)); 206 | 207 | #define LOAD_MSG_9_1(buf) \ 208 | t0 = _mm_blend_epi16(m0,m2,0x03); \ 209 | t1 = _mm_blend_epi16(m1,m2,0x30); \ 210 | t2 = _mm_blend_epi16(t1,t0,0x0F); \ 211 | buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(1,3,0,2)); 212 | 213 | #define LOAD_MSG_9_2(buf) \ 214 | t0 = _mm_slli_si128(m0,4); \ 215 | t1 = _mm_blend_epi16(m1,t0,0xC0); \ 216 | buf = _mm_shuffle_epi32(t1,_MM_SHUFFLE(1,2,0,3)); 217 | 218 | #define LOAD_MSG_9_3(buf) \ 219 | t0 = _mm_unpackhi_epi32(m0,m3); \ 220 | t1 = _mm_unpacklo_epi32(m2,m3); \ 221 | t2 = _mm_unpackhi_epi64(t0,t1); \ 222 | buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(3,0,2,1)); 223 | 224 | #define LOAD_MSG_9_4(buf) \ 225 | t0 = _mm_blend_epi16(m3,m2,0xC0); \ 226 | t1 = _mm_unpacklo_epi32(m0,m3); \ 227 | t2 = _mm_blend_epi16(t0,t1,0x0F); \ 228 | buf = _mm_shuffle_epi32(t2,_MM_SHUFFLE(0,1,2,3)); 229 | 230 | #endif 231 | 232 | -------------------------------------------------------------------------------- /impl/blake2s-load-xop.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2S_LOAD_XOP_H__ 17 | #define __BLAKE2S_LOAD_XOP_H__ 18 | 19 | #define TOB(x) ((x)*4*0x01010101 + 0x03020100) /* ..or not TOB */ 20 | 21 | #if 0 22 | /* Basic VPPERM emulation, for testing purposes */ 23 | static __m128i _mm_perm_epi8(const __m128i src1, const __m128i src2, const __m128i sel) 24 | { 25 | const __m128i sixteen = _mm_set1_epi8(16); 26 | const __m128i t0 = _mm_shuffle_epi8(src1, sel); 27 | const __m128i s1 = _mm_shuffle_epi8(src2, _mm_sub_epi8(sel, sixteen)); 28 | const __m128i mask = _mm_or_si128(_mm_cmpeq_epi8(sel, sixteen), 29 | _mm_cmpgt_epi8(sel, sixteen)); /* (>=16) = 0xff : 00 */ 30 | return _mm_blendv_epi8(t0, s1, mask); 31 | } 32 | #endif 33 | 34 | #define LOAD_MSG_0_1(buf) \ 35 | buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(6),TOB(4),TOB(2),TOB(0)) ); 36 | 37 | #define LOAD_MSG_0_2(buf) \ 38 | buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(7),TOB(5),TOB(3),TOB(1)) ); 39 | 40 | #define LOAD_MSG_0_3(buf) \ 41 | buf = _mm_perm_epi8(m2, m3, _mm_set_epi32(TOB(6),TOB(4),TOB(2),TOB(0)) ); 42 | 43 | #define LOAD_MSG_0_4(buf) \ 44 | buf = _mm_perm_epi8(m2, m3, _mm_set_epi32(TOB(7),TOB(5),TOB(3),TOB(1)) ); 45 | 46 | #define LOAD_MSG_1_1(buf) \ 47 | t0 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(0),TOB(5),TOB(0),TOB(0)) ); \ 48 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(6)) ); 49 | 50 | #define LOAD_MSG_1_2(buf) \ 51 | t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(2),TOB(0),TOB(4),TOB(6)) ); \ 52 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) ); 53 | 54 | #define LOAD_MSG_1_3(buf) \ 55 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(0),TOB(0),TOB(1)) ); \ 56 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) ); 57 | 58 | #define LOAD_MSG_1_4(buf) \ 59 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(7),TOB(2),TOB(0)) ); \ 60 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(4)) ); 61 | 62 | #define LOAD_MSG_2_1(buf) \ 63 | t0 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(0),TOB(1),TOB(0),TOB(7)) ); \ 64 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(4),TOB(0)) ); 65 | 66 | #define LOAD_MSG_2_2(buf) \ 67 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(2),TOB(0),TOB(4)) ); \ 68 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(0)) ); 69 | 70 | #define LOAD_MSG_2_3(buf) \ 71 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(7),TOB(3),TOB(0)) ); \ 72 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(6)) ); 73 | 74 | #define LOAD_MSG_2_4(buf) \ 75 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(4),TOB(1),TOB(6),TOB(0)) ); \ 76 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(6)) ); 77 | 78 | #define LOAD_MSG_3_1(buf) \ 79 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(3),TOB(7)) ); \ 80 | t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) ); \ 81 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(5),TOB(1),TOB(0)) ); 82 | 83 | #define LOAD_MSG_3_2(buf) \ 84 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(0),TOB(1),TOB(5)) ); \ 85 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(6),TOB(4),TOB(1),TOB(0)) ); 86 | 87 | #define LOAD_MSG_3_3(buf) \ 88 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(4),TOB(5),TOB(2)) ); \ 89 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) ); 90 | 91 | #define LOAD_MSG_3_4(buf) \ 92 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(6)) ); \ 93 | buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(4),TOB(2),TOB(6),TOB(0)) ); 94 | 95 | #define LOAD_MSG_4_1(buf) \ 96 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(2),TOB(5),TOB(0)) ); \ 97 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(6),TOB(2),TOB(1),TOB(5)) ); 98 | 99 | #define LOAD_MSG_4_2(buf) \ 100 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(4),TOB(7),TOB(0)) ); \ 101 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) ); 102 | 103 | #define LOAD_MSG_4_3(buf) \ 104 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(6),TOB(0),TOB(0)) ); \ 105 | t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(2),TOB(7),TOB(0)) ); \ 106 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(6)) ); 107 | 108 | #define LOAD_MSG_4_4(buf) \ 109 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(4),TOB(0),TOB(1)) ); \ 110 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(4),TOB(0)) ); 111 | 112 | #define LOAD_MSG_5_1(buf) \ 113 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(6),TOB(2)) ); \ 114 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(4),TOB(2),TOB(1),TOB(0)) ); 115 | 116 | #define LOAD_MSG_5_2(buf) \ 117 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(6),TOB(0)) ); \ 118 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(4)) ); 119 | 120 | #define LOAD_MSG_5_3(buf) \ 121 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(1),TOB(0),TOB(7),TOB(4)) ); \ 122 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) ); 123 | 124 | #define LOAD_MSG_5_4(buf) \ 125 | t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(5),TOB(0),TOB(1),TOB(0)) ); \ 126 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(6),TOB(1),TOB(5)) ); 127 | 128 | #define LOAD_MSG_6_1(buf) \ 129 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(4),TOB(0),TOB(1),TOB(0)) ); \ 130 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(6),TOB(1),TOB(4)) ); 131 | 132 | #define LOAD_MSG_6_2(buf) \ 133 | t1 = _mm_perm_epi8(m1, m2, _mm_set_epi32(TOB(6),TOB(0),TOB(0),TOB(1)) ); \ 134 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(5),TOB(7),TOB(0)) ); 135 | 136 | #define LOAD_MSG_6_3(buf) \ 137 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(6),TOB(0)) ); \ 138 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(4),TOB(5),TOB(1),TOB(0)) ); 139 | 140 | #define LOAD_MSG_6_4(buf) \ 141 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(2),TOB(3),TOB(7)) ); \ 142 | buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(7),TOB(2),TOB(1),TOB(0)) ); 143 | 144 | #define LOAD_MSG_7_1(buf) \ 145 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(3),TOB(0),TOB(7),TOB(0)) ); \ 146 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(4),TOB(1),TOB(5)) ); 147 | 148 | #define LOAD_MSG_7_2(buf) \ 149 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(5),TOB(1),TOB(0),TOB(7)) ); \ 150 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(6),TOB(0)) ); 151 | 152 | #define LOAD_MSG_7_3(buf) \ 153 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(2),TOB(0),TOB(0),TOB(5)) ); \ 154 | t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(4),TOB(1),TOB(0)) ); \ 155 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(7),TOB(0)) ); 156 | 157 | #define LOAD_MSG_7_4(buf) \ 158 | t1 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(6),TOB(4),TOB(0)) ); \ 159 | buf = _mm_perm_epi8(t1, m2, _mm_set_epi32(TOB(6),TOB(2),TOB(1),TOB(0)) ); 160 | 161 | #define LOAD_MSG_8_1(buf) \ 162 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(6)) ); \ 163 | t0 = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(7),TOB(1),TOB(0)) ); \ 164 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(6),TOB(0)) ); 165 | 166 | #define LOAD_MSG_8_2(buf) \ 167 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(4),TOB(3),TOB(5),TOB(0)) ); \ 168 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(1),TOB(7)) ); 169 | 170 | #define LOAD_MSG_8_3(buf) \ 171 | t0 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(6),TOB(1),TOB(0),TOB(0)) ); \ 172 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(3),TOB(2),TOB(5),TOB(4)) ); \ 173 | 174 | #define LOAD_MSG_8_4(buf) \ 175 | buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(4),TOB(7),TOB(2)) ); 176 | 177 | #define LOAD_MSG_9_1(buf) \ 178 | t0 = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(1),TOB(7),TOB(0),TOB(0)) ); \ 179 | buf = _mm_perm_epi8(t0, m2, _mm_set_epi32(TOB(3),TOB(2),TOB(4),TOB(6)) ); 180 | 181 | #define LOAD_MSG_9_2(buf) \ 182 | buf = _mm_perm_epi8(m0, m1, _mm_set_epi32(TOB(5),TOB(6),TOB(4),TOB(2)) ); 183 | 184 | #define LOAD_MSG_9_3(buf) \ 185 | t0 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(3),TOB(5),TOB(0)) ); \ 186 | buf = _mm_perm_epi8(t0, m3, _mm_set_epi32(TOB(5),TOB(2),TOB(1),TOB(7)) ); 187 | 188 | #define LOAD_MSG_9_4(buf) \ 189 | t1 = _mm_perm_epi8(m0, m2, _mm_set_epi32(TOB(0),TOB(0),TOB(0),TOB(7)) ); \ 190 | buf = _mm_perm_epi8(t1, m3, _mm_set_epi32(TOB(3),TOB(4),TOB(6),TOB(0)) ); 191 | 192 | #endif 193 | 194 | -------------------------------------------------------------------------------- /impl/blake2s-ref.c: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - reference C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "blake2.h" 20 | #include "blake2-impl.h" 21 | 22 | static const uint32_t blake2s_IV[8] = 23 | { 24 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 25 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 26 | }; 27 | 28 | static const uint8_t blake2s_sigma[10][16] = 29 | { 30 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 31 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 32 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 33 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 34 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 35 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 36 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 37 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 38 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 39 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 40 | }; 41 | 42 | BLAKE2_LOCAL_INLINE(int) blake2s_set_lastnode( blake2s_state *S ) 43 | { 44 | S->f[1] = -1; 45 | return 0; 46 | } 47 | 48 | BLAKE2_LOCAL_INLINE(int) blake2s_clear_lastnode( blake2s_state *S ) 49 | { 50 | S->f[1] = 0; 51 | return 0; 52 | } 53 | 54 | /* Some helper functions, not necessarily useful */ 55 | BLAKE2_LOCAL_INLINE(int) blake2s_is_lastblock( const blake2s_state *S ) 56 | { 57 | return S->f[0] != 0; 58 | } 59 | 60 | BLAKE2_LOCAL_INLINE(int) blake2s_set_lastblock( blake2s_state *S ) 61 | { 62 | if( S->last_node ) blake2s_set_lastnode( S ); 63 | 64 | S->f[0] = -1; 65 | return 0; 66 | } 67 | 68 | BLAKE2_LOCAL_INLINE(int) blake2s_clear_lastblock( blake2s_state *S ) 69 | { 70 | if( S->last_node ) blake2s_clear_lastnode( S ); 71 | 72 | S->f[0] = 0; 73 | return 0; 74 | } 75 | 76 | BLAKE2_LOCAL_INLINE(int) blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) 77 | { 78 | S->t[0] += inc; 79 | S->t[1] += ( S->t[0] < inc ); 80 | return 0; 81 | } 82 | 83 | /* Parameter-related functions */ 84 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) 85 | { 86 | P->digest_length = digest_length; 87 | return 0; 88 | } 89 | 90 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) 91 | { 92 | P->fanout = fanout; 93 | return 0; 94 | } 95 | 96 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) 97 | { 98 | P->depth = depth; 99 | return 0; 100 | } 101 | 102 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) 103 | { 104 | store32( &P->leaf_length, leaf_length ); 105 | return 0; 106 | } 107 | 108 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) 109 | { 110 | store48( P->node_offset, node_offset ); 111 | return 0; 112 | } 113 | 114 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) 115 | { 116 | P->node_depth = node_depth; 117 | return 0; 118 | } 119 | 120 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) 121 | { 122 | P->inner_length = inner_length; 123 | return 0; 124 | } 125 | 126 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) 127 | { 128 | memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); 129 | return 0; 130 | } 131 | 132 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) 133 | { 134 | memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); 135 | return 0; 136 | } 137 | 138 | BLAKE2_LOCAL_INLINE(int) blake2s_init0( blake2s_state *S ) 139 | { 140 | int i; 141 | memset( S, 0, sizeof( blake2s_state ) ); 142 | 143 | for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; 144 | 145 | return 0; 146 | } 147 | 148 | /* init2 xors IV with input parameter block */ 149 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) 150 | { 151 | const uint32_t *p = ( const uint32_t * )( P ); 152 | size_t i; 153 | 154 | blake2s_init0( S ); 155 | 156 | /* IV XOR ParamBlock */ 157 | for( i = 0; i < 8; ++i ) 158 | S->h[i] ^= load32( &p[i] ); 159 | 160 | return 0; 161 | } 162 | 163 | 164 | /* Sequential blake2s initialization */ 165 | int blake2s_init( blake2s_state *S, const uint8_t outlen ) 166 | { 167 | blake2s_param P[1]; 168 | 169 | /* Move interval verification here? */ 170 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 171 | 172 | P->digest_length = outlen; 173 | P->key_length = 0; 174 | P->fanout = 1; 175 | P->depth = 1; 176 | store32( &P->leaf_length, 0 ); 177 | store48( &P->node_offset, 0 ); 178 | P->node_depth = 0; 179 | P->inner_length = 0; 180 | /* memset(P->reserved, 0, sizeof(P->reserved) ); */ 181 | memset( P->salt, 0, sizeof( P->salt ) ); 182 | memset( P->personal, 0, sizeof( P->personal ) ); 183 | return blake2s_init_param( S, P ); 184 | } 185 | 186 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 187 | { 188 | blake2s_param P[1]; 189 | 190 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 191 | 192 | if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; 193 | 194 | P->digest_length = outlen; 195 | P->key_length = keylen; 196 | P->fanout = 1; 197 | P->depth = 1; 198 | store32( &P->leaf_length, 0 ); 199 | store48( &P->node_offset, 0 ); 200 | P->node_depth = 0; 201 | P->inner_length = 0; 202 | /* memset(P->reserved, 0, sizeof(P->reserved) ); */ 203 | memset( P->salt, 0, sizeof( P->salt ) ); 204 | memset( P->personal, 0, sizeof( P->personal ) ); 205 | 206 | if( blake2s_init_param( S, P ) < 0 ) return -1; 207 | 208 | { 209 | uint8_t block[BLAKE2S_BLOCKBYTES]; 210 | memset( block, 0, BLAKE2S_BLOCKBYTES ); 211 | memcpy( block, key, keylen ); 212 | blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); 213 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 214 | } 215 | return 0; 216 | } 217 | 218 | static int blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) 219 | { 220 | uint32_t m[16]; 221 | uint32_t v[16]; 222 | size_t i; 223 | 224 | for( i = 0; i < 16; ++i ) 225 | m[i] = load32( block + i * sizeof( m[i] ) ); 226 | 227 | for( i = 0; i < 8; ++i ) 228 | v[i] = S->h[i]; 229 | 230 | v[ 8] = blake2s_IV[0]; 231 | v[ 9] = blake2s_IV[1]; 232 | v[10] = blake2s_IV[2]; 233 | v[11] = blake2s_IV[3]; 234 | v[12] = S->t[0] ^ blake2s_IV[4]; 235 | v[13] = S->t[1] ^ blake2s_IV[5]; 236 | v[14] = S->f[0] ^ blake2s_IV[6]; 237 | v[15] = S->f[1] ^ blake2s_IV[7]; 238 | #define G(r,i,a,b,c,d) \ 239 | do { \ 240 | a = a + b + m[blake2s_sigma[r][2*i+0]]; \ 241 | d = rotr32(d ^ a, 16); \ 242 | c = c + d; \ 243 | b = rotr32(b ^ c, 12); \ 244 | a = a + b + m[blake2s_sigma[r][2*i+1]]; \ 245 | d = rotr32(d ^ a, 8); \ 246 | c = c + d; \ 247 | b = rotr32(b ^ c, 7); \ 248 | } while(0) 249 | #define ROUND(r) \ 250 | do { \ 251 | G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ 252 | G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ 253 | G(r,2,v[ 2],v[ 6],v[10],v[14]); \ 254 | G(r,3,v[ 3],v[ 7],v[11],v[15]); \ 255 | G(r,4,v[ 0],v[ 5],v[10],v[15]); \ 256 | G(r,5,v[ 1],v[ 6],v[11],v[12]); \ 257 | G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ 258 | G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ 259 | } while(0) 260 | ROUND( 0 ); 261 | ROUND( 1 ); 262 | ROUND( 2 ); 263 | ROUND( 3 ); 264 | ROUND( 4 ); 265 | ROUND( 5 ); 266 | ROUND( 6 ); 267 | ROUND( 7 ); 268 | ROUND( 8 ); 269 | ROUND( 9 ); 270 | 271 | for( i = 0; i < 8; ++i ) 272 | S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; 273 | 274 | #undef G 275 | #undef ROUND 276 | return 0; 277 | } 278 | 279 | 280 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ) 281 | { 282 | while( inlen > 0 ) 283 | { 284 | size_t left = S->buflen; 285 | size_t fill = 2 * BLAKE2S_BLOCKBYTES - left; 286 | 287 | if( inlen > fill ) 288 | { 289 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ 290 | S->buflen += fill; 291 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 292 | blake2s_compress( S, S->buf ); /* Compress */ 293 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); /* Shift buffer left */ 294 | S->buflen -= BLAKE2S_BLOCKBYTES; 295 | in += fill; 296 | inlen -= fill; 297 | } 298 | else /* inlen <= fill */ 299 | { 300 | memcpy( S->buf + left, in, (size_t)inlen ); 301 | S->buflen += (size_t)inlen; /* Be lazy, do not compress */ 302 | in += inlen; 303 | inlen -= inlen; 304 | } 305 | } 306 | 307 | return 0; 308 | } 309 | 310 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ) 311 | { 312 | uint8_t buffer[BLAKE2S_OUTBYTES] = {0}; 313 | int i; 314 | 315 | if( out == NULL || outlen == 0 || outlen > BLAKE2S_OUTBYTES ) 316 | return -1; 317 | 318 | if( blake2s_is_lastblock( S ) ) 319 | return -1; 320 | 321 | 322 | if( S->buflen > BLAKE2S_BLOCKBYTES ) 323 | { 324 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 325 | blake2s_compress( S, S->buf ); 326 | S->buflen -= BLAKE2S_BLOCKBYTES; 327 | memmove( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); 328 | } 329 | 330 | blake2s_increment_counter( S, ( uint32_t )S->buflen ); 331 | blake2s_set_lastblock( S ); 332 | memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ 333 | blake2s_compress( S, S->buf ); 334 | 335 | for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 336 | store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 337 | 338 | memcpy( out, buffer, outlen ); 339 | return 0; 340 | } 341 | 342 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 343 | { 344 | blake2s_state S[1]; 345 | 346 | /* Verify parameters */ 347 | if ( NULL == in && inlen > 0 ) return -1; 348 | 349 | if ( NULL == out ) return -1; 350 | 351 | if ( NULL == key && keylen > 0) return -1; 352 | 353 | if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 354 | 355 | if( keylen > BLAKE2S_KEYBYTES ) return -1; 356 | 357 | if( keylen > 0 ) 358 | { 359 | if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; 360 | } 361 | else 362 | { 363 | if( blake2s_init( S, outlen ) < 0 ) return -1; 364 | } 365 | 366 | blake2s_update( S, ( const uint8_t * )in, inlen ); 367 | blake2s_final( S, out, outlen ); 368 | return 0; 369 | } 370 | 371 | #if defined(SUPERCOP) 372 | int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) 373 | { 374 | return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 ); 375 | } 376 | #endif 377 | 378 | #if defined(BLAKE2S_SELFTEST) 379 | #include 380 | #include "blake2-kat.h" 381 | int main( int argc, char **argv ) 382 | { 383 | uint8_t key[BLAKE2S_KEYBYTES]; 384 | uint8_t buf[KAT_LENGTH]; 385 | size_t i; 386 | 387 | for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) 388 | key[i] = ( uint8_t )i; 389 | 390 | for( i = 0; i < KAT_LENGTH; ++i ) 391 | buf[i] = ( uint8_t )i; 392 | 393 | for( i = 0; i < KAT_LENGTH; ++i ) 394 | { 395 | uint8_t hash[BLAKE2S_OUTBYTES]; 396 | blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ); 397 | 398 | if( 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) 399 | { 400 | puts( "error" ); 401 | return -1; 402 | } 403 | } 404 | 405 | puts( "ok" ); 406 | return 0; 407 | } 408 | #endif 409 | 410 | 411 | -------------------------------------------------------------------------------- /impl/blake2s-round.h: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | #pragma once 16 | #ifndef __BLAKE2S_ROUND_H__ 17 | #define __BLAKE2S_ROUND_H__ 18 | 19 | #define LOADU(p) _mm_loadu_si128( (const __m128i *)(p) ) 20 | #define STOREU(p,r) _mm_storeu_si128((__m128i *)(p), r) 21 | 22 | #define TOF(reg) _mm_castsi128_ps((reg)) 23 | #define TOI(reg) _mm_castps_si128((reg)) 24 | 25 | #define LIKELY(x) __builtin_expect((x),1) 26 | 27 | 28 | /* Microarchitecture-specific macros */ 29 | #ifndef HAVE_XOP 30 | #ifdef HAVE_SSSE3 31 | #define _mm_roti_epi32(r, c) ( \ 32 | (8==-(c)) ? _mm_shuffle_epi8(r,r8) \ 33 | : (16==-(c)) ? _mm_shuffle_epi8(r,r16) \ 34 | : _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) )) ) 35 | #else 36 | #define _mm_roti_epi32(r, c) _mm_xor_si128(_mm_srli_epi32( (r), -(c) ),_mm_slli_epi32( (r), 32-(-(c)) )) 37 | #endif 38 | #else 39 | /* ... */ 40 | #endif 41 | 42 | 43 | #define G1(row1,row2,row3,row4,buf) \ 44 | row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \ 45 | row4 = _mm_xor_si128( row4, row1 ); \ 46 | row4 = _mm_roti_epi32(row4, -16); \ 47 | row3 = _mm_add_epi32( row3, row4 ); \ 48 | row2 = _mm_xor_si128( row2, row3 ); \ 49 | row2 = _mm_roti_epi32(row2, -12); 50 | 51 | #define G2(row1,row2,row3,row4,buf) \ 52 | row1 = _mm_add_epi32( _mm_add_epi32( row1, buf), row2 ); \ 53 | row4 = _mm_xor_si128( row4, row1 ); \ 54 | row4 = _mm_roti_epi32(row4, -8); \ 55 | row3 = _mm_add_epi32( row3, row4 ); \ 56 | row2 = _mm_xor_si128( row2, row3 ); \ 57 | row2 = _mm_roti_epi32(row2, -7); 58 | 59 | #define DIAGONALIZE(row1,row2,row3,row4) \ 60 | row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(2,1,0,3) ); \ 61 | row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \ 62 | row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(0,3,2,1) ); 63 | 64 | #define UNDIAGONALIZE(row1,row2,row3,row4) \ 65 | row4 = _mm_shuffle_epi32( row4, _MM_SHUFFLE(0,3,2,1) ); \ 66 | row3 = _mm_shuffle_epi32( row3, _MM_SHUFFLE(1,0,3,2) ); \ 67 | row2 = _mm_shuffle_epi32( row2, _MM_SHUFFLE(2,1,0,3) ); 68 | 69 | #if defined(HAVE_XOP) 70 | #include "blake2s-load-xop.h" 71 | #elif defined(HAVE_SSE41) 72 | #include "blake2s-load-sse41.h" 73 | #else 74 | #include "blake2s-load-sse2.h" 75 | #endif 76 | 77 | #define ROUND(r) \ 78 | LOAD_MSG_ ##r ##_1(buf1); \ 79 | G1(row1,row2,row3,row4,buf1); \ 80 | LOAD_MSG_ ##r ##_2(buf2); \ 81 | G2(row1,row2,row3,row4,buf2); \ 82 | DIAGONALIZE(row1,row2,row3,row4); \ 83 | LOAD_MSG_ ##r ##_3(buf3); \ 84 | G1(row1,row2,row3,row4,buf3); \ 85 | LOAD_MSG_ ##r ##_4(buf4); \ 86 | G2(row1,row2,row3,row4,buf4); \ 87 | UNDIAGONALIZE(row1,row2,row3,row4); \ 88 | 89 | #endif 90 | 91 | -------------------------------------------------------------------------------- /impl/blake2s.c: -------------------------------------------------------------------------------- 1 | /* 2 | BLAKE2 reference source code package - optimized C implementations 3 | 4 | Copyright 2012, Samuel Neves . You may use this under the 5 | terms of the CC0, the OpenSSL Licence, or the Apache Public License 2.0, at 6 | your option. The terms of these licenses can be found at: 7 | 8 | - CC0 1.0 Universal : http://creativecommons.org/publicdomain/zero/1.0 9 | - OpenSSL license : https://www.openssl.org/source/license.html 10 | - Apache 2.0 : http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | More information about the BLAKE2 hash function can be found at 13 | https://blake2.net. 14 | */ 15 | 16 | #include 17 | #include 18 | 19 | #include "blake2.h" 20 | #include "blake2-impl.h" 21 | 22 | #include "blake2-config.h" 23 | 24 | 25 | #include 26 | #if defined(HAVE_SSSE3) 27 | #include 28 | #endif 29 | #if defined(HAVE_SSE41) 30 | #include 31 | #endif 32 | #if defined(HAVE_AVX) 33 | #include 34 | #endif 35 | #if defined(HAVE_XOP) 36 | #include 37 | #endif 38 | 39 | #include "blake2s-round.h" 40 | 41 | static const uint32_t blake2s_IV[8] = 42 | { 43 | 0x6A09E667UL, 0xBB67AE85UL, 0x3C6EF372UL, 0xA54FF53AUL, 44 | 0x510E527FUL, 0x9B05688CUL, 0x1F83D9ABUL, 0x5BE0CD19UL 45 | }; 46 | 47 | static const uint8_t blake2s_sigma[10][16] = 48 | { 49 | { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , 50 | { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , 51 | { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , 52 | { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , 53 | { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , 54 | { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , 55 | { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , 56 | { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , 57 | { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , 58 | { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , 59 | }; 60 | 61 | 62 | /* Some helper functions, not necessarily useful */ 63 | BLAKE2_LOCAL_INLINE(int) blake2s_set_lastnode( blake2s_state *S ) 64 | { 65 | S->f[1] = -1; 66 | return 0; 67 | } 68 | 69 | BLAKE2_LOCAL_INLINE(int) blake2s_clear_lastnode( blake2s_state *S ) 70 | { 71 | S->f[1] = 0; 72 | return 0; 73 | } 74 | 75 | BLAKE2_LOCAL_INLINE(int) blake2s_is_lastblock( const blake2s_state *S ) 76 | { 77 | return S->f[0] != 0; 78 | } 79 | 80 | BLAKE2_LOCAL_INLINE(int) blake2s_set_lastblock( blake2s_state *S ) 81 | { 82 | if( S->last_node ) blake2s_set_lastnode( S ); 83 | 84 | S->f[0] = -1; 85 | return 0; 86 | } 87 | 88 | BLAKE2_LOCAL_INLINE(int) blake2s_clear_lastblock( blake2s_state *S ) 89 | { 90 | if( S->last_node ) blake2s_clear_lastnode( S ); 91 | 92 | S->f[0] = 0; 93 | return 0; 94 | } 95 | 96 | BLAKE2_LOCAL_INLINE(int) blake2s_increment_counter( blake2s_state *S, const uint32_t inc ) 97 | { 98 | uint64_t t = ( ( uint64_t )S->t[1] << 32 ) | S->t[0]; 99 | t += inc; 100 | S->t[0] = ( uint32_t )( t >> 0 ); 101 | S->t[1] = ( uint32_t )( t >> 32 ); 102 | return 0; 103 | } 104 | 105 | 106 | /* Parameter-related functions */ 107 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_digest_length( blake2s_param *P, const uint8_t digest_length ) 108 | { 109 | P->digest_length = digest_length; 110 | return 0; 111 | } 112 | 113 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_fanout( blake2s_param *P, const uint8_t fanout ) 114 | { 115 | P->fanout = fanout; 116 | return 0; 117 | } 118 | 119 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_max_depth( blake2s_param *P, const uint8_t depth ) 120 | { 121 | P->depth = depth; 122 | return 0; 123 | } 124 | 125 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_leaf_length( blake2s_param *P, const uint32_t leaf_length ) 126 | { 127 | P->leaf_length = leaf_length; 128 | return 0; 129 | } 130 | 131 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_node_offset( blake2s_param *P, const uint64_t node_offset ) 132 | { 133 | store48( P->node_offset, node_offset ); 134 | return 0; 135 | } 136 | 137 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_node_depth( blake2s_param *P, const uint8_t node_depth ) 138 | { 139 | P->node_depth = node_depth; 140 | return 0; 141 | } 142 | 143 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_inner_length( blake2s_param *P, const uint8_t inner_length ) 144 | { 145 | P->inner_length = inner_length; 146 | return 0; 147 | } 148 | 149 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_salt( blake2s_param *P, const uint8_t salt[BLAKE2S_SALTBYTES] ) 150 | { 151 | memcpy( P->salt, salt, BLAKE2S_SALTBYTES ); 152 | return 0; 153 | } 154 | 155 | BLAKE2_LOCAL_INLINE(int) blake2s_param_set_personal( blake2s_param *P, const uint8_t personal[BLAKE2S_PERSONALBYTES] ) 156 | { 157 | memcpy( P->personal, personal, BLAKE2S_PERSONALBYTES ); 158 | return 0; 159 | } 160 | 161 | BLAKE2_LOCAL_INLINE(int) blake2s_init0( blake2s_state *S ) 162 | { 163 | int i; 164 | memset( S, 0, sizeof( blake2s_state ) ); 165 | 166 | for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; 167 | 168 | return 0; 169 | } 170 | 171 | /* init2 xors IV with input parameter block */ 172 | int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) 173 | { 174 | /*blake2s_init0( S ); */ 175 | const uint8_t * v = ( const uint8_t * )( blake2s_IV ); 176 | const uint8_t * p = ( const uint8_t * )( P ); 177 | uint8_t * h = ( uint8_t * )( S->h ); 178 | int i; 179 | /* IV XOR ParamBlock */ 180 | memset( S, 0, sizeof( blake2s_state ) ); 181 | 182 | for( i = 0; i < BLAKE2S_OUTBYTES; ++i ) h[i] = v[i] ^ p[i]; 183 | 184 | return 0; 185 | } 186 | 187 | 188 | /* Some sort of default parameter block initialization, for sequential blake2s */ 189 | int blake2s_init( blake2s_state *S, const uint8_t outlen ) 190 | { 191 | const blake2s_param P = 192 | { 193 | outlen, 194 | 0, 195 | 1, 196 | 1, 197 | 0, 198 | {0}, 199 | 0, 200 | 0, 201 | {0}, 202 | {0} 203 | }; 204 | /* Move interval verification here? */ 205 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 206 | return blake2s_init_param( S, &P ); 207 | } 208 | 209 | 210 | int blake2s_init_key( blake2s_state *S, const uint8_t outlen, const void *key, const uint8_t keylen ) 211 | { 212 | const blake2s_param P = 213 | { 214 | outlen, 215 | keylen, 216 | 1, 217 | 1, 218 | 0, 219 | {0}, 220 | 0, 221 | 0, 222 | {0}, 223 | {0} 224 | }; 225 | 226 | /* Move interval verification here? */ 227 | if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; 228 | 229 | if ( ( !key ) || ( !keylen ) || keylen > BLAKE2S_KEYBYTES ) return -1; 230 | 231 | if( blake2s_init_param( S, &P ) < 0 ) 232 | return -1; 233 | 234 | { 235 | uint8_t block[BLAKE2S_BLOCKBYTES]; 236 | memset( block, 0, BLAKE2S_BLOCKBYTES ); 237 | memcpy( block, key, keylen ); 238 | blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); 239 | secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from stack */ 240 | } 241 | return 0; 242 | } 243 | 244 | 245 | BLAKE2_LOCAL_INLINE(int) blake2s_compress( blake2s_state *S, const uint8_t block[BLAKE2S_BLOCKBYTES] ) 246 | { 247 | __m128i row1, row2, row3, row4; 248 | __m128i buf1, buf2, buf3, buf4; 249 | #if defined(HAVE_SSE41) 250 | __m128i t0, t1; 251 | #if !defined(HAVE_XOP) 252 | __m128i t2; 253 | #endif 254 | #endif 255 | __m128i ff0, ff1; 256 | #if defined(HAVE_SSSE3) && !defined(HAVE_XOP) 257 | const __m128i r8 = _mm_set_epi8( 12, 15, 14, 13, 8, 11, 10, 9, 4, 7, 6, 5, 0, 3, 2, 1 ); 258 | const __m128i r16 = _mm_set_epi8( 13, 12, 15, 14, 9, 8, 11, 10, 5, 4, 7, 6, 1, 0, 3, 2 ); 259 | #endif 260 | #if defined(HAVE_SSE41) 261 | const __m128i m0 = LOADU( block + 00 ); 262 | const __m128i m1 = LOADU( block + 16 ); 263 | const __m128i m2 = LOADU( block + 32 ); 264 | const __m128i m3 = LOADU( block + 48 ); 265 | #else 266 | const uint32_t m0 = ( ( uint32_t * )block )[ 0]; 267 | const uint32_t m1 = ( ( uint32_t * )block )[ 1]; 268 | const uint32_t m2 = ( ( uint32_t * )block )[ 2]; 269 | const uint32_t m3 = ( ( uint32_t * )block )[ 3]; 270 | const uint32_t m4 = ( ( uint32_t * )block )[ 4]; 271 | const uint32_t m5 = ( ( uint32_t * )block )[ 5]; 272 | const uint32_t m6 = ( ( uint32_t * )block )[ 6]; 273 | const uint32_t m7 = ( ( uint32_t * )block )[ 7]; 274 | const uint32_t m8 = ( ( uint32_t * )block )[ 8]; 275 | const uint32_t m9 = ( ( uint32_t * )block )[ 9]; 276 | const uint32_t m10 = ( ( uint32_t * )block )[10]; 277 | const uint32_t m11 = ( ( uint32_t * )block )[11]; 278 | const uint32_t m12 = ( ( uint32_t * )block )[12]; 279 | const uint32_t m13 = ( ( uint32_t * )block )[13]; 280 | const uint32_t m14 = ( ( uint32_t * )block )[14]; 281 | const uint32_t m15 = ( ( uint32_t * )block )[15]; 282 | #endif 283 | row1 = ff0 = LOADU( &S->h[0] ); 284 | row2 = ff1 = LOADU( &S->h[4] ); 285 | row3 = _mm_setr_epi32( 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A ); 286 | row4 = _mm_xor_si128( _mm_setr_epi32( 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 ), LOADU( &S->t[0] ) ); 287 | ROUND( 0 ); 288 | ROUND( 1 ); 289 | ROUND( 2 ); 290 | ROUND( 3 ); 291 | ROUND( 4 ); 292 | ROUND( 5 ); 293 | ROUND( 6 ); 294 | ROUND( 7 ); 295 | ROUND( 8 ); 296 | ROUND( 9 ); 297 | STOREU( &S->h[0], _mm_xor_si128( ff0, _mm_xor_si128( row1, row3 ) ) ); 298 | STOREU( &S->h[4], _mm_xor_si128( ff1, _mm_xor_si128( row2, row4 ) ) ); 299 | return 0; 300 | } 301 | 302 | /* inlen now in bytes */ 303 | int blake2s_update( blake2s_state *S, const uint8_t *in, uint64_t inlen ) 304 | { 305 | while( inlen > 0 ) 306 | { 307 | size_t left = S->buflen; 308 | size_t fill = 2 * BLAKE2S_BLOCKBYTES - left; 309 | 310 | if( inlen > fill ) 311 | { 312 | memcpy( S->buf + left, in, fill ); /* Fill buffer */ 313 | S->buflen += fill; 314 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 315 | blake2s_compress( S, S->buf ); /* Compress */ 316 | memcpy( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); /* Shift buffer left */ 317 | S->buflen -= BLAKE2S_BLOCKBYTES; 318 | in += fill; 319 | inlen -= fill; 320 | } 321 | else /* inlen <= fill */ 322 | { 323 | memcpy( S->buf + left, in, inlen ); 324 | S->buflen += inlen; /* Be lazy, do not compress */ 325 | in += inlen; 326 | inlen -= inlen; 327 | } 328 | } 329 | 330 | return 0; 331 | } 332 | 333 | /* Is this correct? */ 334 | int blake2s_final( blake2s_state *S, uint8_t *out, uint8_t outlen ) 335 | { 336 | uint8_t buffer[BLAKE2S_OUTBYTES] = {0}; 337 | int i; 338 | 339 | if( outlen > BLAKE2S_OUTBYTES ) 340 | return -1; 341 | 342 | if( blake2s_is_lastblock( S ) ) 343 | return -1; 344 | 345 | if( S->buflen > BLAKE2S_BLOCKBYTES ) 346 | { 347 | blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); 348 | blake2s_compress( S, S->buf ); 349 | S->buflen -= BLAKE2S_BLOCKBYTES; 350 | memmove( S->buf, S->buf + BLAKE2S_BLOCKBYTES, S->buflen ); 351 | } 352 | 353 | blake2s_increment_counter( S, ( uint32_t )S->buflen ); 354 | blake2s_set_lastblock( S ); 355 | memset( S->buf + S->buflen, 0, 2 * BLAKE2S_BLOCKBYTES - S->buflen ); /* Padding */ 356 | blake2s_compress( S, S->buf ); 357 | 358 | for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ 359 | store32( buffer + sizeof( S->h[i] ) * i, S->h[i] ); 360 | 361 | memcpy( out, buffer, outlen ); 362 | return 0; 363 | } 364 | 365 | /* inlen, at least, should be uint64_t. Others can be size_t. */ 366 | int blake2s( uint8_t *out, const void *in, const void *key, const uint8_t outlen, const uint64_t inlen, uint8_t keylen ) 367 | { 368 | blake2s_state S[1]; 369 | 370 | /* Verify parameters */ 371 | if ( NULL == in && inlen > 0 ) return -1; 372 | 373 | if ( NULL == out ) return -1; 374 | 375 | if ( NULL == key && keylen > 0) return -1; 376 | 377 | if( !outlen || outlen > BLAKE2S_OUTBYTES ) return -1; 378 | 379 | if( keylen > BLAKE2S_KEYBYTES ) return -1; 380 | 381 | if( keylen > 0 ) 382 | { 383 | if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; 384 | } 385 | else 386 | { 387 | if( blake2s_init( S, outlen ) < 0 ) return -1; 388 | } 389 | 390 | blake2s_update( S, ( const uint8_t * )in, inlen ); 391 | blake2s_final( S, out, outlen ); 392 | return 0; 393 | } 394 | 395 | #if defined(SUPERCOP) 396 | int crypto_hash( unsigned char *out, unsigned char *in, unsigned long long inlen ) 397 | { 398 | return blake2s( out, in, NULL, BLAKE2S_OUTBYTES, inlen, 0 ); 399 | } 400 | #endif 401 | 402 | #if defined(BLAKE2S_SELFTEST) 403 | #include 404 | #include "blake2-kat.h" 405 | int main( int argc, char **argv ) 406 | { 407 | uint8_t key[BLAKE2S_KEYBYTES]; 408 | uint8_t buf[KAT_LENGTH]; 409 | size_t i; 410 | 411 | for( i = 0; i < BLAKE2S_KEYBYTES; ++i ) 412 | key[i] = ( uint8_t )i; 413 | 414 | for( i = 0; i < KAT_LENGTH; ++i ) 415 | buf[i] = ( uint8_t )i; 416 | 417 | for( i = 0; i < KAT_LENGTH; ++i ) 418 | { 419 | uint8_t hash[BLAKE2S_OUTBYTES]; 420 | 421 | if( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 || 422 | 0 != memcmp( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) 423 | { 424 | puts( "error" ); 425 | return -1; 426 | } 427 | } 428 | 429 | puts( "ok" ); 430 | return 0; 431 | } 432 | #endif 433 | 434 | 435 | -------------------------------------------------------------------------------- /pyblake2_impl_common.h: -------------------------------------------------------------------------------- 1 | #ifndef _MSC_VER 2 | # include 3 | #else 4 | typedef unsigned __int8 uint8_t; 5 | typedef unsigned __int32 uint32_t; 6 | typedef unsigned __int64 uint64_t; 7 | # ifndef inline 8 | # define inline __forceinline 9 | # endif 10 | #endif 11 | 12 | /* Optimization choice support */ 13 | #if defined(BLAKE2_COMPRESS_XOP) 14 | # define HAVE_XOP 15 | # define USE_OPTIMIZED_IMPL 16 | #elif defined(BLAKE2_COMPRESS_AVX) 17 | # define HAVE_AVX 18 | # define USE_OPTIMIZED_IMPL 19 | #elif defined(BLAKE2_COMPRESS_SSSE3) 20 | # define HAVE_SSSE3 21 | # define USE_OPTIMIZED_IMPL 22 | #elif defined(BLAKE2_COMPRESS_SSE2) 23 | # define HAVE_SSE2 24 | # define USE_OPTIMIZED_IMPL 25 | #elif defined(BLAKE2_COMPRESS_AUTO) 26 | 27 | /* Auto-detect optimization based on CFLAGS (from upstream) */ 28 | # if defined(__SSE2__) || defined(__x86_64__) || defined(__amd64__) 29 | # define HAVE_SSE2 30 | # endif 31 | # if defined(__SSSE3__) 32 | # define HAVE_SSSE3 33 | # endif 34 | # if defined(__SSE4_1__) 35 | # define HAVE_SSE41 36 | # endif 37 | # if defined(__AVX__) 38 | # define HAVE_AVX 39 | # endif 40 | # if defined(__XOP__) 41 | # define HAVE_XOP 42 | # endif 43 | 44 | /* pure SSE2 implementation is very slow, so only use the more optimized SSSE3+ 45 | * https://github.com/dchest/pyblake2/issues/11 */ 46 | # if defined(__SSSE3__) || defined(__SSE4_1__) || defined(__AVX__) || defined(__XOP__) 47 | # define USE_OPTIMIZED_IMPL 48 | # endif 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /pyblake2module.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Written in 2013 by Dmitry Chestnykh 3 | * 4 | * To the extent possible under law, the author have dedicated all 5 | * copyright and related and neighboring rights to this software to 6 | * the public domain worldwide. This software is distributed without 7 | * any warranty. http://creativecommons.org/publicdomain/zero/1.0/ 8 | */ 9 | 10 | #include 11 | 12 | #include "pyblake2_impl_common.h" 13 | #include "impl/blake2.h" 14 | #include "impl/blake2-impl.h" /* for secure_zero_memory() and store48() */ 15 | 16 | PyDoc_STRVAR(pyblake2__doc__, 17 | "pyblake2 is an extension module implementing BLAKE2 hash function\n" 18 | "with hashlib-compatible interface.\n" 19 | "\n" 20 | "Examples:\n" 21 | "\n" 22 | " >>> from pyblake2 import blake2s\n" 23 | " >>> blake2s(b'cats').hexdigest()\n" 24 | " 'c473a8d190c3867bdaf6529e8d8531925e824cff07f17d489233fde665979f0c'\n" 25 | "\n" 26 | " >>> from pyblake2 import blake2b\n" 27 | " >>> h = blake2b(digest_size = 20)\n" 28 | " >>> h.update(b'Take that, Keccak')\n" 29 | " >>> h.digest()\n" 30 | " '\\x98\\xb37\\xfa\\xf5\\xbc\\tY\\xca\\x12\\x19\\x12\\xbd\\xfa" 31 | "\\xd8\\x13z\\xf9\\xffl'\n" 32 | ); 33 | 34 | 35 | /* 36 | * Python 2-3 compatibility macros. 37 | */ 38 | #if PY_MAJOR_VERSION >= 3 39 | # define COMPAT_PYINT_AS_LONG PyLong_AsLong 40 | # define COMPAT_PYINT_FROM_LONG PyLong_FromLong 41 | # define COMPAT_PYSTRING_FROM_STRING PyUnicode_FromString 42 | # define COMPAT_PYSTRING_FROM_STRING_AND_SIZE PyUnicode_FromStringAndSize 43 | # define COMPAT_PYBYTES_FROM_STRING_AND_SIZE PyBytes_FromStringAndSize 44 | # define BYTES_FMT "y" 45 | #else 46 | # define COMPAT_PYINT_AS_LONG PyInt_AsLong 47 | # define COMPAT_PYINT_FROM_LONG PyInt_FromLong 48 | # define COMPAT_PYSTRING_FROM_STRING PyString_FromString 49 | # define COMPAT_PYSTRING_FROM_STRING_AND_SIZE PyString_FromStringAndSize 50 | # define COMPAT_PYBYTES_FROM_STRING_AND_SIZE PyString_FromStringAndSize 51 | # define BYTES_FMT "s" 52 | #endif 53 | 54 | /* 55 | * Minimum size of buffer when updating hash 56 | * object for GIL to be released. 57 | */ 58 | #define GIL_MINSIZE 2048 59 | 60 | #ifdef WITH_THREAD 61 | # include "pythread.h" 62 | 63 | # define OBJECT_LOCK_FIELD PyThread_type_lock lock; 64 | 65 | # define ACQUIRE_LOCK(obj) \ 66 | if ((obj)->lock) { \ 67 | if (!PyThread_acquire_lock((obj)->lock, 0)) { \ 68 | Py_BEGIN_ALLOW_THREADS \ 69 | PyThread_acquire_lock((obj)->lock, 1); \ 70 | Py_END_ALLOW_THREADS \ 71 | } \ 72 | } 73 | 74 | # define RELEASE_LOCK(obj) \ 75 | if ((obj)->lock) { \ 76 | PyThread_release_lock((obj)->lock); \ 77 | } 78 | 79 | # define INIT_LOCK(obj) do { \ 80 | (obj)->lock = NULL; \ 81 | } while (0) 82 | 83 | # define FREE_LOCK(obj) \ 84 | if ((obj)->lock) { \ 85 | PyThread_free_lock((obj)->lock); \ 86 | (obj)->lock = NULL; \ 87 | } 88 | 89 | #else 90 | # define OBJECT_LOCK_FIELD 91 | # define ACQUIRE_LOCK(obj) 92 | # define RELEASE_LOCK(obj) 93 | # define INIT_LOCK(obj) 94 | # define FREE_LOCK(obj) 95 | #endif /* !WITH_THREAD */ 96 | 97 | static inline int 98 | getbuffer(PyObject *obj, Py_buffer *bp) { 99 | if (PyUnicode_Check(obj)) { 100 | PyErr_SetString(PyExc_TypeError, 101 | "Unicode-objects must be encoded before hashing"); 102 | return 0; 103 | } 104 | if (!PyObject_CheckBuffer(obj)) { 105 | PyErr_SetString(PyExc_TypeError, 106 | "object supporting the buffer API required"); 107 | return 0; 108 | } 109 | 110 | if (PyObject_GetBuffer(obj, bp, PyBUF_SIMPLE) == -1) 111 | return 0; 112 | 113 | if (bp->ndim > 1) { 114 | PyErr_SetString(PyExc_BufferError, "Buffer must be single dimension"); 115 | PyBuffer_Release(bp); 116 | return 0; 117 | } 118 | return 1; 119 | } 120 | 121 | static void 122 | tohex(char *dst, uint8_t *src, size_t srclen) 123 | { 124 | static char hexdigits[] = "0123456789abcdef"; 125 | size_t i; 126 | 127 | for (i = 0; i < srclen; i++) { 128 | dst[i*2 + 0] = hexdigits[(src[i] >> 4) & 0x0f]; 129 | dst[i*2 + 1] = hexdigits[src[i] & 0x0f]; 130 | } 131 | } 132 | 133 | /* 134 | * Helpers for setting node offset. 135 | */ 136 | 137 | static inline int 138 | blake2b_set_node_offset(blake2b_param *param, uint64_t offset) 139 | { 140 | store64(¶m->node_offset, offset); 141 | return 1; 142 | } 143 | 144 | static inline int 145 | blake2s_set_node_offset(blake2s_param *param, uint64_t offset) 146 | { 147 | if (offset > 0xFFFFFFFFFFFFULL) /* maximum 2**48 - 1 */ 148 | return 0; 149 | 150 | store48(¶m->node_offset, offset); 151 | return 1; 152 | } 153 | 154 | /* 155 | * Unleash the macros! 156 | */ 157 | 158 | #define DECL_BLAKE2_STRUCT(name) \ 159 | static PyTypeObject name##Type; \ 160 | \ 161 | typedef struct { \ 162 | PyObject_HEAD \ 163 | name##_param param; \ 164 | name##_state state; \ 165 | OBJECT_LOCK_FIELD \ 166 | } name##Object; 167 | 168 | 169 | #define DECL_NEW_BLAKE2_OBJECT(name) \ 170 | static name##Object * \ 171 | new_##name##Object(void) \ 172 | { \ 173 | name##Object *obj; \ 174 | obj = (name##Object *)PyObject_New(name##Object, &name##Type); \ 175 | if (obj != NULL) INIT_LOCK(obj); \ 176 | return obj; \ 177 | } 178 | 179 | 180 | static char *kwlist[] = { 181 | "data", "digest_size", "key", "salt", "person", 182 | "fanout", "depth", "leaf_size", "node_offset", 183 | "node_depth", "inner_size", "last_node", NULL 184 | }; 185 | 186 | #define DECL_INIT_BLAKE2_OBJECT(name, bigname) \ 187 | static int \ 188 | init_##name##Object(name##Object *self, PyObject *args, PyObject *kw) \ 189 | { \ 190 | Py_buffer buf, key, salt, person; \ 191 | PyObject *data = NULL, *last_node_obj = NULL, *fanout_obj = NULL, \ 192 | *depth_obj = NULL; \ 193 | unsigned int leaf_size = 0; \ 194 | unsigned PY_LONG_LONG node_offset = 0; \ 195 | int node_depth = 0, inner_size = 0, digest_size = bigname##_OUTBYTES; \ 196 | long fanout = 1, depth = 1; \ 197 | \ 198 | /* Initialize buffers. */ \ 199 | key.buf = salt.buf = person.buf = NULL; \ 200 | \ 201 | /* Parse arguments. */ \ 202 | if (!PyArg_ParseTupleAndKeywords(args, kw, \ 203 | "|" /* following arguments are optional */ \ 204 | "O" /* `data` as PyObject */ \ 205 | "i" /* `digest_size` as int */ \ 206 | BYTES_FMT"*" /* `key` as Py_buffer */ \ 207 | BYTES_FMT"*" /* `salt` as Py_buffer */ \ 208 | BYTES_FMT"*" /* `person` as Py_buffer */ \ 209 | "O" /* `fanout` as PyObject */ \ 210 | "O" /* `depth` as PyObject */ \ 211 | "I" /* `leaf_size` as unsigned int */ \ 212 | "K" /* `node_offset` as unsigned PY_LONG_LONG*/ \ 213 | "i" /* `node_depth` as int */ \ 214 | "i" /* `inner_size` as int */ \ 215 | "O" /* `last_node` as PyObject */ \ 216 | ":"#name"", /* function name for errors */ \ 217 | kwlist, &data, &digest_size, &key, &salt, &person, \ 218 | &fanout_obj, &depth_obj, &leaf_size, &node_offset, \ 219 | &node_depth, &inner_size, &last_node_obj)) \ 220 | goto err0; \ 221 | \ 222 | /* Zero parameter block. */ \ 223 | memset(&self->param, 0, sizeof(self->param)); \ 224 | \ 225 | /* Set digest size. */ \ 226 | if (digest_size <= 0 || digest_size > bigname##_OUTBYTES) { \ 227 | PyErr_Format(PyExc_ValueError, \ 228 | "digest_size must be between 1 and %d bytes", \ 229 | bigname##_OUTBYTES); \ 230 | goto err0; \ 231 | } \ 232 | self->param.digest_length = digest_size; \ 233 | \ 234 | /* Set salt parameter. */ \ 235 | if (salt.buf != NULL) { \ 236 | if (salt.len > bigname##_SALTBYTES) { \ 237 | PyErr_Format(PyExc_ValueError, \ 238 | "maximum salt length is %d bytes", \ 239 | bigname##_SALTBYTES); \ 240 | goto err0; \ 241 | } \ 242 | memcpy(self->param.salt, salt.buf, salt.len); \ 243 | } \ 244 | \ 245 | /* Set personalization parameter. */ \ 246 | if (person.buf != NULL) { \ 247 | if (person.len > bigname##_PERSONALBYTES) { \ 248 | PyErr_Format(PyExc_ValueError, \ 249 | "maximum person length is %d bytes", \ 250 | bigname##_PERSONALBYTES); \ 251 | goto err0; \ 252 | } \ 253 | memcpy(self->param.personal, person.buf, person.len); \ 254 | } \ 255 | \ 256 | /* Set tree parameters. */ \ 257 | if (fanout_obj != NULL) { \ 258 | fanout = COMPAT_PYINT_AS_LONG(fanout_obj); \ 259 | if (fanout == -1 && PyErr_Occurred()) \ 260 | goto err0; \ 261 | } \ 262 | if (fanout < 0 || fanout > 255) { \ 263 | PyErr_SetString(PyExc_ValueError, \ 264 | "fanout must be between 0 and 255"); \ 265 | goto err0; \ 266 | } \ 267 | self->param.fanout = (uint8_t)fanout; \ 268 | \ 269 | if (depth_obj != NULL) { \ 270 | depth = COMPAT_PYINT_AS_LONG(depth_obj); \ 271 | if (depth == -1 && PyErr_Occurred()) \ 272 | goto err0; \ 273 | } \ 274 | if (depth <= 0 || depth > 255) { \ 275 | PyErr_SetString(PyExc_ValueError, \ 276 | "depth must be between 1 and 255"); \ 277 | goto err0; \ 278 | } \ 279 | self->param.depth = (uint8_t)depth; \ 280 | \ 281 | store32(&self->param.leaf_length, leaf_size); \ 282 | \ 283 | if (!name##_set_node_offset(&self->param, node_offset)) { \ 284 | PyErr_SetString(PyExc_ValueError, "node_offset is too large"); \ 285 | goto err0; \ 286 | } \ 287 | \ 288 | if (node_depth < 0 || node_depth > 255) { \ 289 | PyErr_SetString(PyExc_ValueError, \ 290 | "node_depth must be between 0 and 255"); \ 291 | goto err0; \ 292 | } \ 293 | self->param.node_depth = node_depth; \ 294 | \ 295 | if (inner_size < 0 || inner_size > bigname##_OUTBYTES) { \ 296 | PyErr_Format(PyExc_ValueError, \ 297 | "inner_size must be between 0 and is %d", \ 298 | bigname##_OUTBYTES); \ 299 | goto err0; \ 300 | } \ 301 | self->param.inner_length = inner_size; \ 302 | \ 303 | /* Set key length. */ \ 304 | if (key.buf != NULL && key.len > 0) { \ 305 | if (key.len > bigname##_KEYBYTES) { \ 306 | PyErr_Format(PyExc_ValueError, \ 307 | "maximum key length is %d bytes", \ 308 | bigname##_KEYBYTES); \ 309 | goto err0; \ 310 | } \ 311 | self->param.key_length = key.len; \ 312 | } \ 313 | \ 314 | /* Initialize hash state. */ \ 315 | if (name##_init_param(&self->state, &self->param) < 0) { \ 316 | PyErr_SetString(PyExc_RuntimeError, \ 317 | "error initializing hash state"); \ 318 | goto err0; \ 319 | } \ 320 | \ 321 | /* Set last node flag (must come after initialization). */ \ 322 | self->state.last_node = (last_node_obj != NULL && \ 323 | PyObject_IsTrue(last_node_obj)); \ 324 | \ 325 | /* Process key block if any. */ \ 326 | if (key.buf != NULL && key.len > 0) { \ 327 | uint8_t block[bigname##_BLOCKBYTES]; \ 328 | memset(block, 0, sizeof(block)); \ 329 | memcpy(block, key.buf, key.len); \ 330 | name##_update(&self->state, block, sizeof(block)); \ 331 | secure_zero_memory(block, sizeof(block)); \ 332 | } \ 333 | \ 334 | /* Process initial data if any. */ \ 335 | if (data != NULL) { \ 336 | if (!getbuffer(data, &buf)) \ 337 | goto err0; \ 338 | \ 339 | if (buf.len >= GIL_MINSIZE) { \ 340 | Py_BEGIN_ALLOW_THREADS \ 341 | name##_update(&self->state, buf.buf, buf.len); \ 342 | Py_END_ALLOW_THREADS \ 343 | } else { \ 344 | name##_update(&self->state, buf.buf, buf.len); \ 345 | } \ 346 | PyBuffer_Release(&buf); \ 347 | } \ 348 | \ 349 | /* Release buffers. */ \ 350 | if (key.buf != NULL) \ 351 | PyBuffer_Release(&key); \ 352 | if (salt.buf != NULL) \ 353 | PyBuffer_Release(&salt); \ 354 | if (person.buf != NULL) \ 355 | PyBuffer_Release(&person); \ 356 | \ 357 | return 1; \ 358 | \ 359 | err0: \ 360 | /* Error: release buffers. */ \ 361 | if (key.buf != NULL) \ 362 | PyBuffer_Release(&key); \ 363 | if (salt.buf != NULL) \ 364 | PyBuffer_Release(&salt); \ 365 | if (person.buf != NULL) \ 366 | PyBuffer_Release(&person); \ 367 | \ 368 | return 0; \ 369 | } 370 | 371 | 372 | /* 373 | * Methods. 374 | */ 375 | 376 | #define DECL_PY_BLAKE2_COPY(name) \ 377 | PyDoc_STRVAR(py_##name##_copy__doc__, \ 378 | "Return a copy of the hash object."); \ 379 | \ 380 | static PyObject * \ 381 | py_##name##_copy(name##Object *self, PyObject *unused) \ 382 | { \ 383 | name##Object *cpy; \ 384 | \ 385 | if ((cpy = new_##name##Object()) == NULL) \ 386 | return NULL; \ 387 | \ 388 | ACQUIRE_LOCK(self); \ 389 | cpy->param = self->param; \ 390 | cpy->state = self->state; \ 391 | RELEASE_LOCK(self); \ 392 | return (PyObject *)cpy; \ 393 | } 394 | 395 | 396 | /* 397 | * Macro used inside DECL_PY_BLAKE2_UPDATE: 398 | */ 399 | #ifdef WITH_THREAD 400 | /* With threads: 401 | * Update hash object with buffer, releasing GIL if length of buffer 402 | * is greater than or equal to GIL_MINSIZE. 403 | */ 404 | # define INNER_UPDATE(name) do { \ 405 | if (self->lock == NULL && buf.len >= GIL_MINSIZE) \ 406 | self->lock = PyThread_allocate_lock(); \ 407 | \ 408 | if (self->lock != NULL) { \ 409 | Py_BEGIN_ALLOW_THREADS \ 410 | PyThread_acquire_lock(self->lock, 1); \ 411 | name##_update(&self->state, buf.buf, buf.len); \ 412 | PyThread_release_lock(self->lock); \ 413 | Py_END_ALLOW_THREADS \ 414 | } else { \ 415 | name##_update(&self->state, buf.buf, buf.len); \ 416 | } \ 417 | } while (0) 418 | 419 | #else 420 | /* Without threads: 421 | * just update hash object with buffer. 422 | */ 423 | # define INNER_UPDATE(name) do { \ 424 | name##_update(&self->state, buf.buf, buf.len); \ 425 | } while (0) 426 | 427 | #endif /* !WITH_THREAD */ 428 | 429 | 430 | #define DECL_PY_BLAKE2_UPDATE(name) \ 431 | PyDoc_STRVAR(py_##name##_update__doc__, \ 432 | "Update the hash object with the object, which must be interpretable " \ 433 | "as buffer of bytes."); \ 434 | \ 435 | static PyObject * \ 436 | py_##name##_update(name##Object *self, PyObject *args) \ 437 | { \ 438 | PyObject *obj; \ 439 | Py_buffer buf; \ 440 | \ 441 | if (!PyArg_ParseTuple(args, "O:update", &obj)) \ 442 | return NULL; \ 443 | \ 444 | if (!getbuffer(obj, &buf)) \ 445 | return NULL; \ 446 | \ 447 | INNER_UPDATE(name); \ 448 | PyBuffer_Release(&buf); \ 449 | \ 450 | Py_INCREF(Py_None); \ 451 | return Py_None; \ 452 | } 453 | 454 | 455 | #define DECL_PY_BLAKE2_DIGEST(name, bigname) \ 456 | PyDoc_STRVAR(py_##name##_digest__doc__, \ 457 | "Return the digest of the data so far."); \ 458 | \ 459 | static PyObject * \ 460 | py_##name##_digest(name##Object *self, PyObject *unused) \ 461 | { \ 462 | uint8_t digest[bigname##_OUTBYTES]; \ 463 | name##_state state_cpy; \ 464 | \ 465 | ACQUIRE_LOCK(self); \ 466 | state_cpy = self->state; \ 467 | name##_final(&state_cpy, digest, self->param.digest_length); \ 468 | RELEASE_LOCK(self); \ 469 | return COMPAT_PYBYTES_FROM_STRING_AND_SIZE((const char *)digest, \ 470 | self->param.digest_length); \ 471 | } 472 | 473 | 474 | #define DECL_PY_BLAKE2_HEXDIGEST(name, bigname) \ 475 | PyDoc_STRVAR(py_##name##_hexdigest__doc__, \ 476 | "Like digest() except the digest is returned as a string of double " \ 477 | "length, containing only hexadecimal digits."); \ 478 | \ 479 | static PyObject * \ 480 | py_##name##_hexdigest(name##Object *self, PyObject *unused) \ 481 | { \ 482 | uint8_t digest[bigname##_OUTBYTES]; \ 483 | char hexdigest[sizeof(digest) * 2]; \ 484 | name##_state state_cpy; \ 485 | \ 486 | ACQUIRE_LOCK(self); \ 487 | state_cpy = self->state; \ 488 | name##_final(&state_cpy, digest, self->param.digest_length); \ 489 | tohex(hexdigest, digest, self->param.digest_length); \ 490 | RELEASE_LOCK(self); \ 491 | return COMPAT_PYSTRING_FROM_STRING_AND_SIZE((const char *)hexdigest,\ 492 | self->param.digest_length * 2); \ 493 | } 494 | 495 | 496 | #define DECL_PY_BLAKE2_METHODS(name) \ 497 | static PyMethodDef name##_methods[] = { \ 498 | {"copy", (PyCFunction)py_##name##_copy, METH_NOARGS, \ 499 | py_##name##_copy__doc__}, \ 500 | {"digest", (PyCFunction)py_##name##_digest, METH_NOARGS, \ 501 | py_##name##_digest__doc__}, \ 502 | {"hexdigest", (PyCFunction)py_##name##_hexdigest, METH_NOARGS, \ 503 | py_##name##_hexdigest__doc__}, \ 504 | {"update", (PyCFunction)py_##name##_update, METH_VARARGS, \ 505 | py_##name##_update__doc__}, \ 506 | {NULL, NULL} \ 507 | }; 508 | 509 | /* 510 | * Getters. 511 | */ 512 | 513 | #define DECL_PY_BLAKE2_GET_NAME(name) \ 514 | static PyObject * \ 515 | py_##name##_get_name(name##Object *self, void *closure) \ 516 | { \ 517 | return COMPAT_PYSTRING_FROM_STRING("" #name ""); \ 518 | } 519 | 520 | 521 | #define DECL_PY_BLAKE2_GET_BLOCK_SIZE(name, bigname) \ 522 | static PyObject * \ 523 | py_##name##_get_block_size(name##Object *self, void *closure) \ 524 | { \ 525 | return COMPAT_PYINT_FROM_LONG(bigname##_BLOCKBYTES); \ 526 | } 527 | 528 | 529 | #define DECL_PY_BLAKE2_GET_DIGEST_SIZE(name) \ 530 | static PyObject * \ 531 | py_##name##_get_digest_size(name##Object *self, void *closure) \ 532 | { \ 533 | return COMPAT_PYINT_FROM_LONG(self->param.digest_length); \ 534 | } 535 | 536 | 537 | #define DECL_PY_BLAKE2_GETSETTERS(name) \ 538 | static PyGetSetDef name##_getsetters[] = { \ 539 | {"name", (getter)py_##name##_get_name, \ 540 | NULL, NULL, NULL}, \ 541 | {"block_size", (getter)py_##name##_get_block_size, \ 542 | NULL, NULL, NULL}, \ 543 | {"digest_size", (getter)py_##name##_get_digest_size, \ 544 | NULL, NULL, NULL}, \ 545 | {NULL} \ 546 | }; 547 | 548 | 549 | #define DECL_PY_BLAKE2_DEALLOC(name) \ 550 | static void \ 551 | py_##name##_dealloc(PyObject *self) \ 552 | { \ 553 | name##Object *obj = (name##Object *)self; \ 554 | \ 555 | /* Try not to leave state in memory. */ \ 556 | secure_zero_memory(&obj->param, sizeof(obj->param)); \ 557 | secure_zero_memory(&obj->state, sizeof(obj->state)); \ 558 | FREE_LOCK(obj); \ 559 | PyObject_Del(self); \ 560 | } 561 | 562 | 563 | #define DECL_PY_BLAKE2_TYPE_OBJECT(name) \ 564 | static PyTypeObject name##Type = { \ 565 | PyVarObject_HEAD_INIT(NULL, 0) \ 566 | "pyblake2." #name, /* tp_name */ \ 567 | sizeof(name##Object), /* tp_size */ \ 568 | 0, /* tp_itemsize */ \ 569 | py_##name##_dealloc, /* tp_dealloc */ \ 570 | 0, /* tp_print */ \ 571 | 0, /* tp_getattr */ \ 572 | 0, /* tp_setattr */ \ 573 | 0, /* tp_compare */ \ 574 | 0, /* tp_repr */ \ 575 | 0, /* tp_as_number */ \ 576 | 0, /* tp_as_sequence */ \ 577 | 0, /* tp_as_mapping */ \ 578 | 0, /* tp_hash */ \ 579 | 0, /* tp_call */ \ 580 | 0, /* tp_str */ \ 581 | 0, /* tp_getattro */ \ 582 | 0, /* tp_setattro */ \ 583 | 0, /* tp_as_buffer */ \ 584 | Py_TPFLAGS_DEFAULT, /* tp_flags */ \ 585 | 0, /* tp_doc */ \ 586 | 0, /* tp_traverse */ \ 587 | 0, /* tp_clear */ \ 588 | 0, /* tp_richcompare */ \ 589 | 0, /* tp_weaklistoffset */ \ 590 | 0, /* tp_iter */ \ 591 | 0, /* tp_iternext */ \ 592 | name##_methods, /* tp_methods */ \ 593 | 0, /* tp_members */ \ 594 | name##_getsetters, /* tp_getset */ \ 595 | }; 596 | 597 | 598 | #define DECL_PY_BLAKE2_NEW(name) \ 599 | static PyObject * \ 600 | py_##name##_new(PyObject *self, PyObject *args, PyObject *kwdict) \ 601 | { \ 602 | name##Object *obj; \ 603 | \ 604 | if ((obj = new_##name##Object()) == NULL) \ 605 | goto err0; \ 606 | \ 607 | if (PyErr_Occurred()) \ 608 | goto err1; \ 609 | \ 610 | if (!init_##name##Object(obj, args, kwdict)) \ 611 | goto err1; \ 612 | \ 613 | return (PyObject *)obj; \ 614 | \ 615 | err1: \ 616 | Py_DECREF(obj); \ 617 | err0: \ 618 | return NULL; \ 619 | } 620 | 621 | 622 | #define DECL_BLAKE2_WRAPPER(name, bigname) \ 623 | DECL_BLAKE2_STRUCT(name) \ 624 | DECL_NEW_BLAKE2_OBJECT(name) \ 625 | DECL_INIT_BLAKE2_OBJECT(name, bigname) \ 626 | DECL_PY_BLAKE2_COPY(name) \ 627 | DECL_PY_BLAKE2_UPDATE(name) \ 628 | DECL_PY_BLAKE2_DIGEST(name, bigname) \ 629 | DECL_PY_BLAKE2_HEXDIGEST(name, bigname) \ 630 | DECL_PY_BLAKE2_METHODS(name) \ 631 | DECL_PY_BLAKE2_GET_NAME(name) \ 632 | DECL_PY_BLAKE2_GET_BLOCK_SIZE(name, bigname) \ 633 | DECL_PY_BLAKE2_GET_DIGEST_SIZE(name) \ 634 | DECL_PY_BLAKE2_GETSETTERS(name) \ 635 | DECL_PY_BLAKE2_DEALLOC(name) \ 636 | DECL_PY_BLAKE2_TYPE_OBJECT(name) \ 637 | DECL_PY_BLAKE2_NEW(name) 638 | 639 | /* 640 | * Declare objects. 641 | * Note: don't forget to update module init function and constants. 642 | */ 643 | 644 | PyDoc_STRVAR(py_blake2b_new__doc__, 645 | "blake2b(data=b'', digest_size=64, key=b'', salt=b'', person=b'', " 646 | "fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, " 647 | "inner_size=0, last_node=False) -> blake2b object\n" 648 | "\n" 649 | "Return a new BLAKE2b hash object."); 650 | 651 | DECL_BLAKE2_WRAPPER(blake2b, BLAKE2B) 652 | 653 | 654 | PyDoc_STRVAR(py_blake2s_new__doc__, 655 | "blake2s(data=b'', digest_size=32, key=b'', salt=b'', person=b'', " 656 | "fanout=1, depth=1, leaf_size=0, node_offset=0, node_depth=0, " 657 | "inner_size=0, last_node=False) -> blake2s object\n" 658 | "\n" 659 | "Return a new BLAKE2s hash object."); 660 | 661 | DECL_BLAKE2_WRAPPER(blake2s, BLAKE2S) 662 | 663 | 664 | /* 665 | * Module. 666 | */ 667 | static struct PyMethodDef pyblake2_functions[] = { 668 | {"blake2b", (PyCFunction)py_blake2b_new, METH_VARARGS|METH_KEYWORDS, 669 | py_blake2b_new__doc__}, 670 | {"blake2s", (PyCFunction)py_blake2s_new, METH_VARARGS|METH_KEYWORDS, 671 | py_blake2s_new__doc__}, 672 | {NULL, NULL} 673 | }; 674 | 675 | #if PY_MAJOR_VERSION >= 3 676 | static struct PyModuleDef pyblake2_module = { 677 | PyModuleDef_HEAD_INIT, 678 | "pyblake2", 679 | pyblake2__doc__, 680 | -1, 681 | pyblake2_functions, 682 | NULL, 683 | NULL, 684 | NULL, 685 | NULL 686 | }; 687 | # define INIT_FUNC_NAME PyInit_pyblake2 688 | # define INIT_ERROR return NULL 689 | #else 690 | # define INIT_FUNC_NAME initpyblake2 691 | # define INIT_ERROR return 692 | #endif 693 | 694 | PyMODINIT_FUNC 695 | INIT_FUNC_NAME(void) 696 | { 697 | PyObject *m; 698 | 699 | Py_TYPE(&blake2bType) = &PyType_Type; 700 | if (PyType_Ready(&blake2bType) < 0) 701 | INIT_ERROR; 702 | 703 | Py_TYPE(&blake2sType) = &PyType_Type; 704 | if (PyType_Ready(&blake2sType) < 0) 705 | INIT_ERROR; 706 | 707 | /* TODO: do runtime self-check */ 708 | #if PY_MAJOR_VERSION >= 3 709 | m = PyModule_Create(&pyblake2_module); 710 | #else 711 | m = Py_InitModule3("pyblake2", pyblake2_functions, pyblake2__doc__); 712 | #endif 713 | 714 | /* Add module constants. */ 715 | 716 | PyModule_AddIntConstant(m, "BLAKE2B_SALT_SIZE", BLAKE2B_SALTBYTES); 717 | PyModule_AddIntConstant(m, "BLAKE2B_PERSON_SIZE", BLAKE2B_PERSONALBYTES); 718 | PyModule_AddIntConstant(m, "BLAKE2B_MAX_KEY_SIZE", BLAKE2B_KEYBYTES); 719 | PyModule_AddIntConstant(m, "BLAKE2B_MAX_DIGEST_SIZE", BLAKE2B_OUTBYTES); 720 | 721 | PyModule_AddIntConstant(m, "BLAKE2S_SALT_SIZE", BLAKE2S_SALTBYTES); 722 | PyModule_AddIntConstant(m, "BLAKE2S_PERSON_SIZE", BLAKE2S_PERSONALBYTES); 723 | PyModule_AddIntConstant(m, "BLAKE2S_MAX_KEY_SIZE", BLAKE2S_KEYBYTES); 724 | PyModule_AddIntConstant(m, "BLAKE2S_MAX_DIGEST_SIZE", BLAKE2S_OUTBYTES); 725 | 726 | #if PY_MAJOR_VERSION >= 3 727 | return m; 728 | #endif 729 | } 730 | 731 | /* vim: set expandtab ts=4 sw=4: */ 732 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | pyblake2 is an extension module for Python implementing BLAKE2 hash function. 3 | 4 | BLAKE2 is a cryptographic hash function, which offers highest security while 5 | being as fast as MD5 or SHA-1, and comes in two flavors: 6 | 7 | * BLAKE2b, optimized for 64-bit platforms and produces digests of any size 8 | between 1 and 64 bytes, 9 | 10 | * BLAKE2s, optimized for 8- to 32-bit platforms and produces digests of any 11 | size between 1 and 32 bytes. 12 | 13 | BLAKE2 supports keyed mode (a faster and simpler replacement for HMAC), 14 | salted hashing, personalization, and tree hashing. 15 | 16 | Hash objects from this module follow the API of standard library's 17 | `hashlib` objects. 18 | """ 19 | 20 | from setuptools import setup, Extension 21 | 22 | # Version of optimized implementation to use. 23 | 24 | opt_version = 'BLAKE2_COMPRESS_AUTO' 25 | 26 | # By default, pyblake2 automatically selects the optimization based 27 | # on CPU indicated by CFLAGS. If you'd like to override the default 28 | # choice, you can uncomment one of the following options. Note that 29 | # you might need to add additional machine flags via extra_compile_args 30 | # below. 31 | 32 | #opt_version = 'BLAKE2_COMPRESS_REGS' # fast portable 33 | #opt_version = 'BLAKE2_COMPRESS_SSE2' # x86 SSE2 (slow!) 34 | #opt_version = 'BLAKE2_COMPRESS_SSSE3' # x86 SSSE3 35 | #opt_version = 'BLAKE2_COMPRESS_AVX' # x86 AVX 36 | #opt_version = 'BLAKE2_COMPRESS_XOP' # x86 XOP 37 | 38 | pyblake2 = Extension('pyblake2', 39 | define_macros=[ 40 | (opt_version, '1') 41 | ], 42 | #extra_compile_args = ['-msse4.1'], 43 | sources=[ 44 | 'pyblake2module.c', 45 | 'blake2b_impl.c', 46 | 'blake2s_impl.c', 47 | ], 48 | depends=['*.h']) 49 | 50 | 51 | setup(name='pyblake2', 52 | version='1.1.2', 53 | description='BLAKE2 hash function extension module', 54 | long_description=__doc__, 55 | author='Dmitry Chestnykh', 56 | author_email='dmitry@codingrobots.com', 57 | license='http://creativecommons.org/publicdomain/zero/1.0/', 58 | url='https://github.com/dchest/pyblake2', 59 | ext_modules=[pyblake2], 60 | classifiers=[ 61 | 'Intended Audience :: Developers', 62 | 'Intended Audience :: Information Technology', 63 | 'Intended Audience :: Science/Research', 64 | 'License :: CC0 1.0 Universal (CC0 1.0) Public Domain Dedication', 65 | 'Operating System :: OS Independent', 66 | 'Programming Language :: Python :: 2', 67 | 'Programming Language :: Python :: 2.6', 68 | 'Programming Language :: Python :: 2.7', 69 | 'Programming Language :: Python :: 3', 70 | 'Programming Language :: Python :: 3.0', 71 | 'Programming Language :: Python :: 3.1', 72 | 'Programming Language :: Python :: 3.2', 73 | 'Programming Language :: Python :: 3.3', 74 | 'Programming Language :: Python :: 3.4', 75 | 'Programming Language :: Python :: 3.5', 76 | 'Topic :: Security :: Cryptography' 77 | ] 78 | ) 79 | 80 | -------------------------------------------------------------------------------- /test/bench.py: -------------------------------------------------------------------------------- 1 | import timeit 2 | 3 | HASHES = [ 4 | ("pyblake2", "blake2b"), 5 | ("pyblake2", "blake2s"), 6 | ("hashlib", "md5"), 7 | ("hashlib", "sha1"), 8 | ("hashlib", "sha256"), 9 | ("hashlib", "sha512"), 10 | ] 11 | 12 | SIZES = [64, 128, 1024, 2047, 2048, 1000000] 13 | 14 | SETUP_CODE = """ 15 | from {mod} import {fn} as hasher 16 | data = b'x'*{size} 17 | """ 18 | 19 | BENCH_CODE = """ 20 | h = hasher() 21 | h.update(data) 22 | h.digest() 23 | """ 24 | 25 | def measure(mod, fn, size): 26 | num = 10 27 | best = min(timeit.repeat(BENCH_CODE, 28 | SETUP_CODE.format(mod=mod, fn=fn, size=size), 29 | number=num, repeat=5)) 30 | return num * (size/1024./1024.) / best 31 | 32 | def main(): 33 | for size in SIZES: 34 | print("{0} bytes\n".format(size)) 35 | for mod, fn in HASHES: 36 | mbs = measure(mod, fn, size) 37 | print(" {0}.{1} \t {2:3.0f} MB/s".format(mod, fn, mbs)) 38 | print("") 39 | 40 | if __name__ == "__main__": 41 | main() 42 | -------------------------------------------------------------------------------- /test/threads.py: -------------------------------------------------------------------------------- 1 | """ 2 | Simple script to see if GIL is released when hashing. 3 | "Threaded" benchmark should be ~2x as fast as sequential 4 | if it is, but only on a multicore CPU. 5 | """ 6 | 7 | import hashlib, threading, time 8 | from pyblake2 import blake2b 9 | 10 | class Hasher(threading.Thread): 11 | def __init__(self, hashfn): 12 | threading.Thread.__init__(self) 13 | self.hashfn = hashfn 14 | self.setDaemon(True) 15 | self.start() 16 | 17 | def run(self): 18 | md = self.hashfn() 19 | buf = b'a'*1024*1024 20 | for i in range(1000): 21 | md.update(buf) 22 | print(md.hexdigest()) 23 | 24 | def sequential(hashfn): 25 | md = hashfn() 26 | buf = b'a'*1024*1024 27 | for i in range(1000): 28 | md.update(buf) 29 | print(md.hexdigest()) 30 | 31 | print("pyblake2:") 32 | 33 | t = time.time() 34 | for i in range(2): 35 | sequential(blake2b) 36 | print("blake2b (sequential) {0}".format(time.time() - t)) 37 | 38 | t = time.time() 39 | threads = [Hasher(blake2b) for i in range(2)] 40 | for thread in threads: 41 | thread.join() 42 | print("blake2b (threaded) {0}".format(time.time() - t)) 43 | 44 | print("\nhashlib:") 45 | 46 | t = time.time() 47 | for i in range(2): 48 | sequential(hashlib.sha1) 49 | print("sha1 (sequential) {0}".format(time.time() - t)) 50 | 51 | t = time.time() 52 | threads = [Hasher(hashlib.sha1) for i in range(2)] 53 | for thread in threads: 54 | thread.join() 55 | print("sha1 (threaded) {0}".format(time.time() - t)) 56 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist=py26,py27,py31,py32,py33,py34,py35,py36,pypy,pypy3,py2.7-docs,py3.3-docs 3 | 4 | [testenv] 5 | commands=python test/test.py 6 | 7 | [testenv:py31] 8 | basepython=python3.1 9 | 10 | [testenv:py2.7-docs] 11 | basepython=python2.7 12 | changedir=doc_src 13 | deps=sphinx 14 | commands=sphinx-build -b doctest . {envtmpdir}/doctest 15 | 16 | [testenv:py3.3-docs] 17 | basepython=python3.3 18 | changedir=doc_src 19 | deps=sphinx 20 | commands=sphinx-build -b doctest . {envtmpdir}/doctest 21 | --------------------------------------------------------------------------------