And here’s another one: the Next.js Edge Runtime becomes the fourth full-stack framework supported by Cloudflare Pages

Post Syndicated from Greg Brimble original https://blog.cloudflare.com/next-on-pages/

And here's another one: the Next.js Edge Runtime becomes the fourth full-stack framework supported by Cloudflare Pages

And here's another one: the Next.js Edge Runtime becomes the fourth full-stack framework supported by Cloudflare Pages

You can now deploy Next.js applications which opt in to the Edge Runtime on Cloudflare Pages. Next.js is the fourth full-stack web framework that the Pages platform officially supports, and it is one of the most popular in the ‘Jamstack-y’ space.

Cloudflare Pages started its journey as a platform for static websites, but with last year’s addition of Pages Functions powered by Cloudflare Workers, the platform has progressed to support an even more diverse range of use cases. Pages Functions allows developers to sprinkle in small pieces of server-side code with its simple file-based routing, or, as we’ve seen with the adoption from other frameworks (namely SvelteKit, Remix and Qwik), Pages Functions can be used to power your entire full-stack app. The folks behind Remix previously talked about the advantages of adopting open standards, and we’ve seen this again with Next.js’ Edge Runtime.

Next.js’ Edge Runtime

Next.js’ Edge Runtime is an experimental mode that developers can opt into which results in a different type of application being built. Previously, Next.js applications which relied on server-side rendering (SSR) functionality had to be deployed on a Node.js server. Running a Node.js server has significant overhead, and our Cloudflare Workers platform was fundamentally built on a different technology, V8.

However, when Next.js introduced the Edge Runtime mode in June 2022, we saw the opportunity to bring this widely used framework to our platform. We’re very excited that this is being developed in coordination with the WinterCG standards to ensure interoperability across the various web platforms and to ensure that developers have the choice on where they run their business, without fearing any significant vendor lock-in.

It’s important to note that some existing Next.js apps built for Node.js won’t immediately work on Pages. If your application relies on any Node.js built-ins or long-running processes, then Pages may not support your app with today’s announcement as we’re working on expanding our support for Node.js.

However, we see the migration to the Edge Runtime as an effort that’s worthy of investment, to run your applications, well, on the edge! These applications are cheaper to run, respond faster to users and have the latest features that full-stack frameworks offer. We’re seeing increased interest in third-party npm packages and libraries that support standardized runtimes, and in combination with Cloudflare’s data products (e.g. KV, Durable Objects and D1), we’re confident that the edge is going to be the first place that people will want to deploy applications going forward.

Deploy your Next.js app to Cloudflare Pages

Let’s walk through an example, creating a new Next.js application that opts into this Edge Runtime and deploying it to Cloudflare Pages.

npx create-next-app@latest my-app

This will create a new Next.js app in the my-app folder. The default template comes with a traditional Node.js powered API route, so let’s update that to instead use the Edge Runtime.

// pages/api/hello.js

// Next.js Edge API Routes: https://nextjs.org/docs/api-routes/edge-api-routes

export const config = {
  runtime: 'experimental-edge',
}

export default async function (req) {
  return new Response(
    JSON.stringify({ name: 'John Doe' }),
    {
      status: 200,
      headers: {
        'Content-Type': 'application/json'
      }
    }
  )
}

Thanks to the Edge Runtime adopting the Web API standards, if you’ve ever written a Cloudflare Worker before, this might look familiar.

Next, we can update the global next.config.js configuration file to use the Edge Runtime. This will enable us to use the getServerSideProps() API and server-side render (SSR) our webpages.

// next.config.js

/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    runtime: 'experimental-edge',
  },
  reactStrictMode: true,
  swcMinify: true,
}
module.exports = nextConfig

Finally, we’re ready to deploy the project. Publish it to a GitHub or GitLab repository, create a new Pages project, and select “Next.js” from the list of framework presets. This will configure your project to use the @cloudflare/next-on-pages CLI which builds and transforms your project into something we can deploy on Pages. Navigate to the project settings and add an environment variable, NODE_VERSION set to 14 or greater, as well as the following compatibility flags: streams_enable_constructors and transformstream_enable_standard_constructor. You should now be able to deploy your Next.js application. If you want to read more, you can find a detailed guide in our documentation.

How it runs on Cloudflare Pages

Compatibility Dates and Compatibility Flags

Cloudflare Workers has solved the versioning problem by introducing compatibility dates and compatibility flags. While it has been in beta, Pages Functions has always defaulted to using the oldest version of the Workers runtime. We’ve now introduced controls to allow developers to set these dates and flags on their Pages projects environments.

And here's another one: the Next.js Edge Runtime becomes the fourth full-stack framework supported by Cloudflare Pages

By keeping this date recent, you are able to opt in to the latest features and bug fixes that the Cloudflare Workers runtime offers, but equally, you’re completely free to keep the date on whatever works for you today, and we’ll continue to support the functionality at that point in time, forever. We also allow you to set these dates for your production and preview environments independently which will let you test these changes out safely in a preview deployment before rolling it out in production.

We’ve been working on adding more support for the Streams API to the Workers Runtime, and some of this functionality is gated behind the flags we added to the project earlier. These flags are currently scheduled to graduate and become on-by-default on a future compatibility date, 2022-11-30.

The @cloudflare/next-on-pages CLI

Vercel introduced the Build Output API in July 2022 as a “zero configuration” directory structure which the Vercel platform inherently understands and can deploy. We’ve decided to hook into this same API as a way to build Next.js projects consistently that we can understand and deploy.

The open-source @cloudflare/next-on-pages CLI runs npx vercel build behind the scenes, which produces a .vercel/output directory. This directory conforms to the Build Output API, and of particular interest, contains a config.json, static folder and folder of functions. The @cloudflare/next-on-pages CLI then parses this config.json manifest, and combines all the functions into a single Pages Functions ‘advanced mode’ _worker.js.

At this point, the build is finished. Pages then automatically picks up this _worker.js and deploys it with Pages Functions atop the static directory.

Although currently just an implementation detail, we opted to use this Build Output API for a number of reasons. We’re also exploring other similar functionality natively on the Pages platform. We already have one “magical” directory, the functions directory which we use for the file-based routing of Pages Functions. It’s possible that we offer other fixed directory structures which would reduce the need for configuration of any projects using frameworks which adopt the API. Let us know in Discord if you have any thoughts or preferences on what you would like to see!

Additionally, if more full-stack frameworks do adopt Vercel’s Build Output API, we may have automatic support for them running on Pages with this CLI. We’ve only been experimenting with Next.js here so far (and SvelteKit, Remix and Qwik all have their own way of building their projects on Pages at the moment), but it’s possible that in the future we may converge on a standard approach which could be shared between frameworks and platforms. We’re excited to see how this might transpire. Again, let us know if you have thoughts!

Experimental webpack minification

As part of the compilation from .vercel/output/functions to an _worker.js, the @cloudflare/next-on-pages CLI can perform an experimental minification to give you more space for your application to run on Workers. Right now, most accounts are limited to a maximum script size of 1MB (although this can be raised in some circumstances—get in touch!). You can ordinarily fit quite a lot of code in this, but one thing notable about Next.js’ build process at the moment is that it creates webpack-compiled, fully-formed and fully-isolated functions scripts in each of the directories in .vercel/output/functions. This means that each function ends up looking something like this:

let _ENTRIES = {};
(() => {
  // webpackBootstrap
})();

(self["webpackChunk_N_E"] = self["webpackChunk_N_E"] || []).push([100], {

  123: (() => {
    // webpack chunk #123
  }),
  234: (() => {
    // webpack chunk #234
  }),
  345: (() => {
    // webpack chunk #345
  }),

  // …lots of webpack chunks…

}, () => {
  // webpackRuntimeModules
}]);

export default {
  async fetch(request, env, ctx) {
    return _ENTRIES['some_function'].default.call(request);
  }
}

The script contains everything that’s needed to deploy this function, and most of the logic exists in these webpack chunks, but that means that each function has a lot of code shared with its siblings. Quickly, you’ll reach the 1MB limit, if you naively deployed all these functions together.

Our @cloudflare/next-on-pages --experimental-minify CLI argument deals with this problem by analyzing webpack chunks which are re-used in multiple places in this .vercel/output/functions directory and extracts out that code to a common place. This allows our compiler (esbuild) to efficiently combine this code, without duplicating it in all of these places. This process is experimental for the time being, while we look to make this as efficient as possible, without introducing any bugs as a result. Please file an issue on GitHub if you notice any difference in behavior when using --experimental-minify.

What’s next?

Pages Functions has been in beta for almost a year, and we’re very excited to say that general availability is just around the corner. We’re polishing off the last of the remaining features which includes analytics, logging, and billing. In fact, for billing, we recently made the announcement of how you’ll be able to use the Workers Paid plan to remove the request limits of the Pages Functions beta from November 15.

Finally, we’re also looking at how we can bring Wasm support to Pages Functions which will unlock ever more use-cases for your full-stack applications. Stay tuned for more information on how we’ll be offering this soon.

Try creating a Next.js Edge Runtime application and deploying it to Cloudflare Pages with the example above or by following the guide in our documentation. Let us know if you have any questions or face any issues in Discord or on GitHub, and please report any quirks of the --experimental-minify argument. As always, we’re excited to see what you build!

On the Randomness of Automatic Card Shufflers

Post Syndicated from Bruce Schneier original https://www.schneier.com/blog/archives/2022/10/on-the-randomness-of-automatic-card-shufflers.html

Many years ago, Matt Blaze and I talked about getting our hands on a casino-grade automatic shuffler and looking for vulnerabilities. We never did it—I remember that we didn’t even try very hard—but this article shows that we probably would have found non-random properties:

…the executives had recently discovered that one of their machines had been hacked by a gang of hustlers. The gang used a hidden video camera to record the workings of the card shuffler through a glass window. The images, transmitted to an accomplice outside in the casino parking lot, were played back in slow motion to figure out the sequence of cards in the deck, which was then communicated back to the gamblers inside. The casino lost millions of dollars before the gang were finally caught.

Stanford mathematician Persi Diaconis found other flaws:

With his collaborator Susan Holmes, a statistician at Stanford, Diaconis travelled to the company’s Las Vegas showroom to examine a prototype of their new machine. The pair soon discovered a flaw. Although the mechanical shuffling action appeared random, the mathematicians noticed that the resulting deck still had rising and falling sequences, which meant that they could make predictions about the card order.

New Scientist article behind a paywall. Slashdot thread.

Deploying containers to AWS using ECS and CodePipeline 

Post Syndicated from Jessica Veljanovska original https://www.anchor.com.au/blog/2022/10/deploying-containers-to-aws/

Deploying containers to AWS using ECS and CodePipeline 

In this post, it will look at deploying containers to AWS using ECS and CodePipeline. Note that this is only an overview of the process and is not a complete tutorial on how to set this up. 

Containers 101 

However, before we look at how we can deploy Containers onto AWS, it is first worth looking at why we want to use containers, so what are containers?

Containers provide environments for applications to run in isolation. Unlike virtualisation, containers do not require a full guest operating system for each container instance, instead, they share the kernel and other lower-level components of the host operating system as provided by the underlying containerization platform (the most popular of which is Docker, which we will be using in examples from here onwards). This makes containers more efficient at using the underlying hardware resources to run applications. Since Containers are isolated, they can include all their dependencies separate from other running Containers. Suppose that you have two applications that each require specific, conflicting, versions of Python to run, they will not run correctly if this requirement is not met. With containers, you can run both applications with their own environments and dependencies on the same Host Operating system without conflict. 

Containers are also portable, as a developer you can create, run, and test an image on your local workstation and then deploy the same image into your production environment. Of course, deploying into production is never that simple, but that example highlights the flexibility that containers can afford to developers in creating their applications. 

This is achieved by using images, which are read-only templates that provide the containerization platform the instructions required to run the image as a Container. Each image is built from a DockerFile that provides the specification on how to build the image and can also include other images. This can be as simple or as complicated as it needs to be to successfully run the application.

FROM ubuntu:22.04 

COPY . /app 

RUN make /app 

CMD python /app/app.py

However, it is important to know that each image is made up of different layers, which are created based on each line of instruction in the DockerFile that is used to build the image. Each layer is cached by Docker which provides performance benefits to well optimised DockerFiles and the resulting images they create. When the image is run by Docker it creates a Container that flips the layers from the image and adds a runtime Read-Write layer on top, which can be used for logging and any other activity that the application needs to perform and cannot be read from the image. You can use the same image to run as many Containers (running instances of the image) as you desire. Finally, when a Container is removed, the image is retained and only the Read-Write layer is lost. 


Elastic Container Service 

Elastic Container Service or ECS is AWS’ native Container management system. As an orchestration system it makes it easy to deploy and manage containerized applications at scale with built in scheduling that can allow you to spin up/down Containers at specific times or even configure auto-scaling. ECS has three primary modes of operation, known as launch types. Elastic Container Service or ECS is AWS’ native Container management system. As an orchestration system it makes it easy to deploy and manage containerized applications at scale with built in scheduling that can allow you to spin up/down Containers at specific times or even configure auto-scaling. ECS has three primary modes of operation, known as launch types. The first launch type is the AWS EC2 launch type, where you run the ECS agent on EC2 instances that you maintain and manage. The available resource capacity is dependent on the number and type of EC2 instances that you are using. As you are already billed for the AWS resources consumed (EC2, EBS, etc.), there are no additional charges for using ECS with this launch type. If you are using AWS Outposts, you can use also utilise that capacity instead of Cloud-based EC2 instances. 

The second launch type is the AWS Fargate launch type. This is similar to the EC2 launch type, however, the major difference is that AWS are managing the underlying infrastructure. Because of this there are no inherent capacity constraints, and the billing models is based on the amount of vCPU and memory your Containers consume. 

The last launch type is the External launch type, which is known as ECS Anywhere. This allows you to use the features of ECS with your own on-premises hardware/infrastructure. This is billed at an hourly rate per managed instance. 

ECS operates using a hierarchy that connects together the different aspects of the service and allows flexibility in exactly how the application is run. This hierarchy consists of ECS Clusters, ECS Services, ECS Tasks, and finally the running Containers. We will briefly look at each of these services. ECS Clusters 

ECS Clusters are a logical grouping of ECS Services and their associated ECS Task. A Cluster is where scheduled tasks can be defined, either using fixed intervals or cron expression. If you are using the AWS EC2 Launch Type, it is also where you can configure Auto-Scaling for the EC2 instances in the form of Capacity Providers. 

ECS Services 

ECS Services are responsible for running ECS Tasks. They will ensure that the desired number of Tasks are running and will start new Tasks if an existing Task stops or fails for any reason in order to maintain the desired number of running Tasks. Auto-Scaling can be configured here to automatically update the desired number of Tasks based on CPU and Memory. You can also associate the Service with an Elastic Load Balancer Target Group and if you do this you can also use the number of requests as a metric for Auto-Scaling. 

ECS Tasks 

ECS Tasks are running instances of an ECS Task Definition. The Task Definition describes one or more Containers that make up the Task. This is where the main configuration for the Containers is defined, including the Image/s that are used, the Ports exposed, Environment variables, and if any storage volumes (for example EFS) are required. The Task as a whole can also have Resource sizing configured, which is a hard requirement for Fargate due to its billing model. Task definitions are versioned, so each time you make a change it will create a new revision, allowing you to easily roll back to an older configuration if required.


Elastic Container Registry 

Elastic Container Registry or ECR, is not formally part of ECS but instead supports it. ECR can be used to publicly or privately store Container images and like all AWS services has granular permissions provided using IAM. The main features of ECR, besides its ability to integrate with ECS, is the built-in vulnerability scanning for images, and the lack of throttling limitations that public container registries might impose. It is not a free service though, so you will need to pay for any usage that falls outside of the included Free-Tier inclusions.

ECR is not strictly required for using ECS, you can continue to use whatever image registry you want. However, if you are using a CodePipeline to deploy your Containers we recommend using ECR purely to avoid throttling issues preventing the CodePipeline from successfully running. 


CodePipeline 

In software development, a Pipeline is a collection of multiple tools and services working together in order to achieve a common goal, most commonly building and deploying application code. AWS CodePipeline is AWS’ native form of a Pipeline that supports both AWS services as well as external services in order to help automate deployments/releases.

CodePipeline is one part of the complete set of developer tools that AWS provides, which commonly have names starting with “Code”. This is important as by itself CodePipeline can only orchestrate other tooling. For a Pipeline that will deploy a Container to ECS, we will need AWS CodeCommit, AWS CodeBuild, and AWS CodeDeploy. In addition to running the components that are configured, CodePipeline can also provide and retrieve artifacts stored in S3 for each step. For example, it will store the application code from CodeCommit into S3 and provide this to CodeBuild, Code Build will then take this and will create its own artifact files that are provided to CodeDeploy. 

AWS CodeCommit 

AWS CodeCommit is a fully managed source control service that hosts private Git repositories. While this is not strictly required for the CodePipeline, we recommend using it to ensure that AWS has a cached copy of the code at all times. External git repositories can use actions or their own pipelines to push code to CodeCommit when it has been committed. CodeCommit is used in the Source stage of the CodePipeline to both provide the code that is used and to trigger the Pipeline to run when a commit is made. Alternatively, you can use CodeStar Connections to directly use GitHub or BitBucket as the Source stage instead.

AWS CodeBuild 

AWS CodeBuild is a fully managed integration service that can be used to run commands as defined in the BuildSpec that it draws its configuration from, either in CodeBuild itself, or from the Source repository. This flexibility allows it to compile source code, run tests, make API calls, or in our case build Docker Images using the DockerFile that is part of a code repository. CodeBuild is used in the Build stage of the CodePipeline to build the Docker Image, push it to ECR, and update any Environment Variables used later in the deployment.

The following is an example of what a typical BuildSpec might look like for our purposes. 

version: 0.2
  
  
  phases:
  
    pre_build:
  
      commands:
  
        - echo Logging in to Amazon ECR...
  
        - aws --version
  
        - aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $ACCOUNTID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com
  
    build:
  
      commands:
  
        - echo Build started on `date`
  
        - echo Building the Docker image...
  
        - docker build -t "$REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME" .
  
        - docker tag "$REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME" "$REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME"
  
    post_build:
  
      commands:
  
        - echo Build completed on `date`
  
        - echo Pushing the Docker images...
  
        - docker push "$REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME"
  
        - echo Writing image definitions file...
  
        - printf '{"ImageURI":"%s"}'" $REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME"  > imageDetail.json
  
        - echo $REPOSITORY_URI:$IMAGE_TAG-$CODEBUILD_START_TIME
  
        - sed -i 's|<APP_NAME>|'$IMAGE_REPO_NAME'|g' appspec.yaml taskdef.json
  
        - sed -i 's|<SERVICE_PORT>|'$SERVICE_PORT'|g' appspec.yaml taskdef.json
  
        - sed -i 's|<AWS_ACCOUNT_ID>|'$AWS_ACCOUNT_ID'|g' taskdef.json
  
        - sed -i 's|<MEMORY_RESV>|'$MEMORY_RESV'|g' taskdef.json
  
        - sed -i 's|<IMAGE_NAME>|'$REPOSITORY_URI'\:'$IMAGE_TAG-$CODEBUILD_START_TIME'|g' taskdef.json
  
        - sed -i 's|<IAM_EXEC_ROLE>|'$IAM_EXEC_ROLE'|g' taskdef.json
  
        - sed -i 's|<REGION>|'$REGION'|g' taskdef.json
  
  artifacts:
  
    files:
  
      - appspec.yaml
  
      - taskdef.json
  
      - imageDetail.json

Failures in this step are most likely caused by an incorrect, non-functioning DockerFile or hitting throttling from external Docker repositories. 

AWS CodeDeploy 

AWS CodeDeploy is a fully managed deployment service that integrates with several AWS services including ECS. It can also be used to deploy software to on-premises servers. The configuration of the deployment is defined using an appspec file. CodeDeploy offers several different deployment types and configurations. We tend to use the `Blue/Green` deployment type and the `CodeDeployDefault.ECSAllAtOnce` deployment configuration by default. 

The Blue/Green deployment model allows for the deployment to rollback to the previously deployed Tasks if the deployment is not successful. This makes use of Load Balancer Target Groups to determine if the created Tasks in the ECS Service are healthy. If the health checks fail, then the deployment will fail and trigger a rollback.  

In our ECS CodePipeline, CodeDeploy will run based on the following example appspec.yaml file. Note that the place holder variables in <> are updated with real configuration by the CodeBuild stage.

version: 0.0 

Resources: 

  - TargetService: 

      Type: AWS::ECS::Service 

      Properties: 

        TaskDefinition: <TASK_DEFINITION> 

        LoadBalancerInfo: 

          ContainerName: "<APP_NAME>" 

          ContainerPort: <SERVICE_PORT> 

You may have noticed a lack of configuration regarding the actual Container we will be running up to this point. As we noted earlier, ECS Tasks can use a taskdef file to configure the Task and Containers, which is exactly what we are doing here. One of the files the CodeBuild configuration above expects to be present is taskdef.json. Below is an example taskdef.json file, ss with the appspec.yaml file there are placeholder variables as indicated by <>.


{ 

  "executionRoleArn": "<IAM_EXEC_ROLE>", 

  "containerDefinitions": [ 

    { 

      "name": "<APP_NAME>", 

      "image": "<IMAGE_NAME>", 

      "essential": true, 

      "memoryReservation": <MEMORY_RESV>, 

      "portMappings": [ 

        { 

          "hostPort": 0, 

          "protocol": "tcp", 

          "containerPort": <SERVICE_PORT> 

        } 

      ], 

      "environment": [ 

        { 

          "name": "PORT", 

          "value": "<SERVICE_PORT>" 

        }, 

        { 

          "name": "APP_NAME", 

          "value": "<APP_NAME>" 

        }, 

        { 

          "name": "IMAGE_BUILD_DATE", 

          "value": "<IMAGE_BUILD_DATE>" 

        }, 

      ], 

      "mountPoints": [] 

    } 

  ], 

  "volumes": [], 

  "requiresCompatibilities": [ 

    "EC2" 

  ], 

  "networkMode": "bridge", 

  "family": "<APP_NAME>" 

Failures in this stage of the CodePipeline generally mean that there is something wrong with the Container that is preventing it from starting successfully and passing its health check. Causes of this are varied and rely heavily on having good logging in place. Failures can range from the DockerFile being configured to execute a command that does not exist, to the application itself erroring out when starting for whatever reason might be logged, such as pulling incomplete data from RDS or failing to connect to an external service. 

Summary 

In summary, we have seen what Containers are, why they are useful, and what options AWS provides with its Elastic Container Service (ECS) for running them. Additionally, we looked at what parts of AWS CodePipeline we would need to use in order to deploy our Containers to ECS using CodePipeline.

For further information on the services used, I would highly recommend looking at the documentation that AWS provides. 

For a more hands-on guided walkthrough on setting up ECS and CodePipeline, AWS provide the following resources, there is also plenty of third party material you can find online. 

The post Deploying containers to AWS using ECS and CodePipeline  appeared first on Anchor | Cloud Engineering Services.

Brave New Trusted Boot World

Post Syndicated from original https://0pointer.net/blog/brave-new-trusted-boot-world.html

🔐 Brave New Trusted Boot World 🚀

This document looks at the boot process of general purpose Linux
distributions. It covers the status quo and how we envision Linux boot
to work in the future with a focus on robustness and simplicity.

This document will assume that the reader has comprehensive
familiarity with TPM 2.0 security chips and their capabilities (e.g.,
PCRs, measurements, SRK), boot loaders, the shimbinary, Linux,
initrds, UEFI Firmware, PE binaries, and SecureBoot.

Problem Description

Status quo ante of the boot logic on typical Linux distributions:

  • Most popular Linux distributions generate initrdslocally, and
    they are unsigned, thus not protected through SecureBoot (since that
    would require local SecureBoot key enrollment, which is generally
    not done), nor TPM PCRs.

  • Boot chain is typically Firmware →
    shimgrub → Linux kernel →
    initrd(dracut or similar) → root file system

  • Firmware’s UEFI SecureBoot protects shim, shim’s key management
    protects grub and kernel. No code signing protects initrd. initrd
    acquires the key for encrypted root fs from the user (or
    TPM/FIDO2/PKCS11).

  • shim/grub/kernel is measured into TPM PCR 4, among other stuff

  • EFI TPM event log reports measured data into TPM PCRs, and can be
    used to reconstruct and validate state of TPM PCRs from the used
    resources.

  • No userspace components are typically measured, except for what IMA
    measures

  • New kernels require locally generating new boot loader scripts and
    generating a new initrd each time. OS updates thus mean fragile
    generation of multiple resources and copying multiple files into the
    boot partition.

Problems with the status quo ante:

  • initrd typically unlocks root file system encryption, but is not
    protected whatsoever, and trivial to attack and modify offline

  • OS updates are brittle: PCR values of grub are very hard to
    pre-calculate, as grub measures chosen control flow path, not just
    code images. PCR values vary wildly, and OS provided resources are
    not measured into separate PCRs. Grub’s PCR measurements might be
    useful up to a point to reason about the boot after the fact, for
    the most basic remote attestation purposes, but useless for
    calculating them ahead of time during the OS build process (which
    would be desirable to be able to bind secrets to future expected PCR
    state, for example to bind secrets to an OS in a way that it remain
    accessible even after that OS is updated).

  • Updates of a boot loader are not robust, require multi-file updates
    of ESP and boot partition, and regeneration of boot scripts

  • No rollback protection (no way to cryptographically invalidate
    access to TPM-bound secrets on OS updates)

  • Remote attestation of running software is needlessly complex since
    initrds are generated locally and thus basically are guaranteed to
    vary on each system.

  • Locking resources maintained by arbitrary user apps to TPM state
    (PCRs) is not realistic for general purpose systems, since PCRs will
    change on every OS update, and there’s no mechanism to re-enroll
    each such resource before every OS update, and remove the old
    enrollment after the update.

  • There is no concept to cryptographically invalidate/revoke secrets
    for an older OS version once updated to a new OS version. An
    attacker thus can always access the secrets generated on old OSes if
    they manage to exploit an old version of the OS — even if a newer
    version already has been deployed.

Goals of the new design:

  • Provide a fully signed execution path from firmware to
    userspace, no exceptions

  • Provide a fully measured execution path from firmware to
    userspace, no exceptions

  • Separate out TPM PCRs assignments, by “owner” of measured
    resources, so that resources can be bound to them in a fine-grained
    fashion.

  • Allow easy pre-calculation of expected PCR values based on
    booted kernel/initrd, configuration, local identity of the system

  • Rollback protection

  • Simple & robust updates: one updated file per concept

  • Updates without requiring re-enrollment/local preparation of the
    TPM-protected resources (no more “brittle” PCR hashes that must be
    propagated into every TPM-protected resource on each OS update)

  • System ready for easy remote attestation, to prove validity of
    booted OS, configuration and local identity

  • Ability to bind secrets to specific phases of the boot, e.g. the
    root fs encryption key should be retrievable from the TPM only in
    the initrd, but not after the host transitioned into the root fs.

  • Reasonably secure, automatic, unattended unlocking of disk
    encryption secrets should be possible.

  • “Democratize” use of PCR policies by defining PCR register meanings,
    and making binding to them robust against updates, so that
    external projects can safely and securely bind their own data to
    them (or use them for remote attestation) without risking breakage
    whenever the OS is updated.

  • Build around TPM 2.0 (with graceful fallback for TPM-less
    systems if desired, but TPM 1.2 support is out of scope)

Considered attack scenarios and considerations:

  • Evil Maid: neither online nor offline (i.e. “at rest”), physical
    access to a storage device should enable an attacker to read the
    user’s plaintext data on disk (confidentiality); neither online nor
    offline, physical access to a storage device should allow undetected
    modification/backdooring of user data or OS (integrity), or
    exfiltration of secrets.

  • TPMs are assumed to be reasonably “secure”, i.e. can securely
    store/encrypt secrets. Communication to TPM is not “secure” though
    and must be protected on the wire.

  • Similar, the CPU is assumed to be reasonably “secure”

  • SecureBoot is assumed to be reasonably “secure” to permit validated
    boot up to and including shim+boot loader+kernel (but see discussion
    below)

  • All user data must be encrypted and authenticated. All vendor and
    administrator data must be authenticated.

  • It is assumed all software involved regularly contains
    vulnerabilities and requires frequent updates to address them, plus
    regular revocation of old versions.

  • It is further assumed that key material used for signing code by the
    OS vendor can reasonably be kept secure (via use of HSM, and
    similar, where secret key information never leaves the signing
    hardware) and does not require frequent roll-over.

Proposed Construction

Central to the proposed design is the concept of a Unified Kernel
Image (UKI)
. These UKIs are the combination of a Linux kernel image,
and initrd, a UEFI boot stub program (and further resources, see
below) into one single UEFI PE file that can either be directly
invoked by the UEFI firmware (which is useful in particular in some
cloud/Confidential Computing environments) or through a boot loader
(which is generally useful to implement support for multiple kernel
versions, with interactive or automatic selection of image to boot
into, potentially with automatic fallback management to increase
robustness).

UKI Components

Specifically, UKIs typically consist of the following resources:

  1. An UEFI boot stub that is a small piece of code still running in
    UEFI mode and that transitions into the Linux kernel included in
    the UKI (e.g., as implemented in
    sd-stub,
    see below)

  2. The Linux kernel to boot in the .linux PE section

  3. The initrd that the kernel shall unpack and invoke in the
    .initrd PE section

  4. A kernel command line string, in the .cmdline PE
    section

  5. Optionally, information describing the OS this kernel is intended
    for, in the .osrel PE section (derived from
    /etc/os-release of the booted OS). This is useful for
    presentation of the UKI in the boot loader menu, and ordering it
    against other entries, using the included version information.

  6. Optionally, information describing kernel release information
    (i.e. uname -r output) in the .uname PE
    section. This is also useful for presentation of the UKI in the
    boot loader menu, and ordering it against other entries.

  7. Optionally, a boot splash to bring to screen before transitioning
    into the Linux kernel in the .splash PE section

  8. Optionally, a compiled Devicetree database file, for systems which
    need it, in the .dtb PE section

  9. Optionally, the public key in PEM format that matches the
    signatures of the .pcrsig PE section (see below), in a
    .pcrpkey PE section.

  10. Optionally, a JSON file encoding expected PCR 11 hash values seen
    from userspace once the UKI has booted up, along with signatures
    of these expected PCR 11 hash values, matching a specific public
    key in the.pcrsigPE section. (Note: we use plural
    for “values” and “signatures” here, as this JSON file will
    typically carry a separate value and signature for each PCR bank
    for PCR 11, i.e. one pair of value and signature for the SHA1
    bank, and another pair for the SHA256 bank, and so on. This
    ensures when enrolling or unlocking a TPM-bound secret we’ll
    always have a signature around matching the banks available
    locally (after all, which banks the local hardware supports is up
    to the hardware). For the sake of simplifying this already overly
    complex topic, we’ll pretend in the rest of the text there was
    only one PCR signature per UKI we have to care about, even if this
    is not actually the case.)

Given UKIs are regular UEFI PE files, they can thus be signed as one
for SecureBoot, protecting all of the individual resources listed
above at once, and their combination. Standard Linux tools such as
sbsigntool and pesign can be used to sign
UKI files.

UKIs wrap all of the above data in a single file, hence all of the
above components can be updated in one go through single file atomic
updates, which is useful given that the primary expected storage place
for these UKIs is the UEFI System Partition (ESP), which is a vFAT
file system, with its limited data safety guarantees.

UKIs can be generated via a single, relatively simple objcopy
invocation, that glues the listed components together, generating one
PE binary that then can be signed for SecureBoot. (For details on
building these, see below.)

Note that the primary location to place UKIs in is the EFI System
Partition (or an otherwise firmware accessible file system). This
typically means a VFAT file system of some form. Hence an effective
UKI size limit of 4GiB is in place, as that’s the largest file size a
FAT32 file system supports.

Basic UEFI Stub Execution Flow

The mentioned UEFI stub program will execute the following operations
in UEFI mode before transitioning into the Linux kernel that is
included in its .linux PE section:

  1. The PE sections listed are searched for in the invoked UKI the stub
    is part of, and superficially validated (i.e. general file format is
    in order).

  2. All PE sections listed above of the invoked UKI are measured into
    TPM PCR 11. This TPM PCR is expected to be all zeroes before the UKI
    initializes. Pre-calculation is thus very straight-forward if the
    resources included in the PE image are known. (Note: as a single
    exception the .pcrsig PE section is excluded from this measurement,
    as it is supposed to carry the expected result of the measurement, and
    thus cannot also be input to it, see below for further details about
    this section.)

  3. If the .splash PE section is included in the UKI it is brought onto the screen

  4. If the .dtb PE section is included in the UKI it is activated
    using the Devicetree UEFI “fix-up” protocol

  5. If a command line was passed from the boot loader to the UKI
    executable it is discarded if SecureBoot is enabled and the command
    line from the .cmdline used. If SecureBoot is disabled and a
    command line was passed it is used in place of the one from
    .cmdline. Either way the used command line is measured into TPM
    PCR 12. (This of course removes any flexibility of control of the
    kernel command line of the local user. In many scenarios this is
    probably considered beneficial, but in others it is not, and some
    flexibility might be desired. Thus, this concept probably needs to
    be extended sooner or later, to allow more flexible kernel command
    line policies to be enforced via definitions embedded into the
    UKI. For example: allowing definition of multiple kernel command
    lines the user/boot menu can select one from; allowing additional
    allowlisted parameters to be specified; or even optionally allowing
    any verification of the kernel command line to be turned off even
    in SecureBoot mode. It would then be up to the builder of the UKI
    to decide on the policy of the kernel command line.)

  6. It will set a couple of volatile EFI variables to inform userspace
    about executed TPM PCR measurements (and which PCR registers were
    used), and other execution properties. (For example: the EFI
    variable StubPcrKernelImage in the
    4a67b082-0a4c-41cf-b6c7-440b29bb8c4f vendor namespace indicates
    the PCR register used for the UKI measurement, i.e. the value
    “11”).

  7. An initrd cpio archive is dynamically synthesized from the
    .pcrsig and .pcrpkey PE section data (this is later passed to
    the invoked Linux kernel as additional initrd, to be overlaid with
    the main initrd from the .initrd section). These files are later
    available in the /.extra/ directory in the initrd context.

  8. The Linux kernel from the .linux PE section is invoked with with
    a combined initrd that is composed from the blob from the .initrdPE section, the dynamically generated initrd containing the
    .pcrsig and .pcrpkey PE sections, and possibly some additional
    components like sysexts or syscfgs.

TPM PCR Assignments

In the construction above we take possession of two PCR registers
previously unused on generic Linux distributions:

  • TPM PCR 11 shall contain measurements of all components of the
    UKI (with exception of the .pcrsig PE section, see above). This
    PCR will also contain measurements of the boot phase once userspace
    takes over (see below).

  • TPM PCR 12 shall contain measurements of the used kernel command
    line. (Plus potentially other forms of
    parameterization/configuration passed into the UKI, not discussed in
    this document)

On top of that we intend to define two more PCR registers like this:

  • TPM PCR 15 shall contain measurements of the volume encryption
    key of the root file system of the OS.

  • [TPM PCR 13 shall contain measurements of additional extension
    images for the initrd, to enable a modularized initrd – not covered
    by this document]

(See the Linux TPM PCR
Registry

for an overview how these four PCRs fit into the list of Linux PCR
assignments.)

For all four PCRs the assumption is that they are zero before the UKI
initializes, and only the data that the UKI and the OS measure into
them is included. This makes pre-calculating them straightforward:
given a specific set of UKI components, it is immediately clear what
PCR values can be expected in PCR 11 once the UKI booted up. Given a
kernel command line (and other parameterization/configuration) it is
clear what PCR values are expected in PCR 12.

Note that these four PCRs are defined by the conceptual “owner” of the
resources measured into them. PCR 11 only contains resources the OS
vendor
controls. Thus it is straight-forward for the OS vendor to
pre-calculate and then cryptographically sign the expected values for
PCR 11. The PCR 11 values will be identical on all systems that run
the same version of the UKI. PCR 12 only contains resources the
administrator controls, thus the administrator can pre-calculate
PCR values, and they will be correct on all instances of the OS that
use the same parameters/configuration. PCR 15 only contains resources
inherently local to the local system, i.e. the cryptographic key
material that encrypts the root file system of the OS.

Separating out these three roles does not imply these actually need to
be separate when used. However the assumption is that in many popular
environments these three roles should be separate.

By separating out these PCRs by the owner’s role, it becomes
straightforward to remotely attest, individually, on the software that
runs on a node (PCR 11), the configuration it uses (PCR 12) or the
identity of the system (PCR 15). Moreover, it becomes straightforward
to robustly and securely encrypt data so that it can only be unlocked
on a specific set of systems that share the same OS, or the same
configuration, or have a specific identity – or a combination thereof.

Note that the mentioned PCRs are so far not typically used on generic
Linux-based operating systems, to our knowledge. Windows uses them,
but given that Windows and Linux should typically not be included in
the same boot process this should be unproblematic, as Windows’ use of
these PCRs should thus not conflict with ours.

To summarize:

PCR Purpose Owner Expected Value before UKI boot Pre-Calculable
11 Measurement of UKI components and boot phases OS Vendor Zero Yes
(at UKI build time)
12 Measurement of kernel command line, additional kernel runtime configuration such as systemd credentials, systemd syscfg images Administrator Zero Yes
(when system configuration is assembled)
13 System Extension Images of initrd
(and possibly more)
(Administrator) Zero Yes
15 Measurement of root file system volume key
(Possibly later more: measurement of root file system UUIDs and labels and of the machine ID /etc/machine-id)
Local System Zero Yes
(after first boot once ll such IDs are determined)

Signature Keys

In the model above in particular two sets of private/public key pairs
are relevant:

  • The SecureBoot key to sign the UKI PE executable with. This controls
    permissible choices of OS/kernel

  • The key to sign the expected PCR 11 values with. Signatures made
    with this key will end up in the .pcrsig PE section. The public
    key part will end up in the .pcrpkey PE section.

Typically the key pair for the PCR 11 signatures should be chosen with
a narrow focus, reused for exactly one specific OS (e.g. “Fedora
Desktop Edition”) and the series of UKIs that belong to it (all the
way through all the versions of the OS). The SecureBoot signature key
can be used with a broader focus, if desired. By keeping the PCR 11
signature key narrow in focus one can ensure that secrets bound to the
signature key can only be unlocked on the narrow set of UKIs desired.

TPM Policy Use

Depending on the intended access policy to a resource protected by the
TPM, one or more of the PCRs described above should be selected to
bind TPM policy to.

For example, the root file system encryption key should likely be
bound to TPM PCR 11, so that it can only be unlocked if a specific set
of UKIs is booted (it should then, once acquired, be measured into PCR
15, as discussed above, so that later TPM objects can be bound to it,
further down the chain). With the model described above this is
reasonably straight-forward to do:

  • When userspace wants to bind disk encryption to a specific series of
    UKIs (“enrollment”), it looks for the public key passed to the
    initrd in the /.extra/ directory (which as discussed above
    originates in the .pcrpkey PE section of the UKI). The relevant
    userspace component (e.g. systemd) is then responsible for
    generating a random key to be used as symmetric encryption key for
    the storage volume (let’s call it disk encryption key _here,
    DEK_). The TPM is then used to encrypt (“seal”) the DEK with its
    internal Storage Root Key (TPM SRK). A TPM2 policy is bound to the
    encrypted DEK. The policy enforces that the DEK may only be
    decrypted if a valid signature is provided that matches the state of
    PCR 11 and the public key provided in the /.extra/ directory of
    the initrd. The plaintext DEK key is passed to the kernel to
    implement disk encryption (e.g. LUKS/dm-crypt). (Alternatively,
    hardware disk encryption can be used too, i.e. Intel MKTME, AMD SME
    or even OPAL, all of which are outside of the scope of this
    document.) The TPM-encrypted version of the DEK which the TPM
    returned is written to the encrypted volume’s superblock.

  • When userspace wants to unlock disk encryption on a specific
    UKI, it looks for the signature data passed to the initrd in the
    /.extra/ directory (which as discussed above originates in the
    .pcrsig PE section of the UKI). It then reads the encrypted
    version of the DEK from the superblock of the encrypted volume. The
    signature and the encrypted DEK are then passed to the TPM. The TPM
    then checks if the current PCR 11 state matches the supplied
    signature from the.pcrsig section and the public key used during
    enrollment. If all checks out it decrypts (“unseals”) the DEK and
    passes it back to the OS, where it is then passed to the kernel
    which implements the symmetric part of disk encryption.

Note that in this scheme the encrypted volume’s DEK is not bound
to specific literal PCR hash values, but to a public key which is
expected to sign PCR hash values.

Also note that the state of PCR 11 only matters during unlocking. It
is not used or checked when enrolling.

In this scenario:

  • Input to the TPM part of the enrollment process are the TPM’s
    internal SRK, the plaintext DEK provided by the OS, and the public
    key later used for signing expected PCR values, also provided by the
    OS. – Output is the encrypted (“sealed”) DEK.

  • Input to the TPM part of the unlocking process are the TPM’s
    internal SRK, the current TPM PCR 11 values, the public key used
    during enrollment, a signature that matches both these PCR values
    and the public key, and the encrypted DEK. – Output is the plaintext
    (“unsealed”) DEK.

Note that sealing/unsealing is done entirely on the TPM chip, the host
OS just provides the inputs (well, only the inputs that the TPM chip
doesn’t know already on its own), and receives the outputs. With the
exception of the plaintext DEK, none of the inputs/outputs are
sensitive, and can safely be stored in the open. On the wire the
plaintext DEK is protected via TPM parameter encryption (not discussed
in detail here because though important not in scope for this
document).

TPM PCR 11 is the most important of the mentioned PCRs, and its use is
thus explained in detail here. The other mentioned PCRs can be used in
similar ways, but signatures/public keys must be provided via other
means.

This scheme builds on the functionality Linux’ LUKS2 functionality
provides, i.e. key management supporting multiple slots, and the
ability to embed arbitrary metadata in the encrypted volume’s
superblock. Note that this means the TPM2-based logic explained here
doesn’t have to be the only way to unlock an encrypted volume. For
example, in many setups it is wise to enroll both this TPM-based
mechanism and an additional “recovery key” (i.e. a high-entropy
computer generated passphrase the user can provide manually in case
they lose access to the TPM and need to access their data), of which
either can be used to unlock the volume.

Boot Phases

Secrets needed during boot-up (such as the root file system encryption
key) should typically not be accessible anymore afterwards, to protect
them from access if a system is attacked during runtime. To implement
this the scheme above is extended in one way: at certain milestones of
the boot process additional fixed “words” should be measured into PCR
11. These milestones are placed at conceptual security boundaries,
i.e. whenever code transitions from a higher privileged context to a
less privileged context.

Specifically:

  • When the initrd initializes (“initrd-enter”)

  • When the initrd transitions into the root file system (“initrd-leave”)

  • When the early boot phase of the OS on the root file system has
    completed, i.e. all storage and file systems have been set up and
    mounted, immediately before regular services are started
    (“sysinit”)

  • When the OS on the root file system completed the boot process far
    enough to allow unprivileged users to log in (“complete”)

  • When the OS begins shut down (“shutdown”)

  • When the service manager is mostly finished with shutting down and
    is about to pass control to the final phase of the shutdown logic
    (“final”)

By measuring these additional words into PCR 11 the distinct phases of
the boot process can be distinguished in a relatively straight-forward
fashion and the expected PCR values in each phase can be determined.

The phases are measured into PCR 11 (as opposed to some other PCR)
mostly because available PCRs are scarce, and the boot phases defined
are typically specific to a chosen OS, and hence fit well with the
other data measured into PCR 11: the UKI which is also specific to the
OS. The OS vendor generates both the UKI and defines the boot phases,
and thus can safely and reliably pre-calculate/sign the expected PCR
values for each phase of the boot.

Revocation/Rollback Protection

In order to secure secrets stored at rest, in particular in
environments where unattended decryption shall be possible, it is
essential that an attacker cannot use old, known-buggy – but properly
signed – versions of software to access them.

Specifically, if disk encryption is bound to an OS vendor (via UKIs
that include expected PCR values, signed by the vendor’s public key)
there must be a mechanism to lock out old versions of the OS or UKI
from accessing TPM based secrets once it is determined that the old
version is vulnerable.

To implement this we propose making use of one of the “counters” TPM
2.0 devices provide: integer registers that are persistent in the TPM
and can only be increased on request of the OS, but never be
decreased. When sealing resources to the TPM, a policy may be declared
to the TPM that restricts how the resources can later be unlocked:
here we use one that requires that along with the expected PCR values
(as discussed above) a counter integer range is provided to the TPM
chip, along with a suitable signature covering both, matching the
public key provided during sealing. The sealing/unsealing mechanism
described above is thus extended: the signature passed to the TPM
during unsealing now covers both the expected PCR values and the
expected counter range. To be able to use a signature associated with
an UKI provided by the vendor to unseal a resource, the counter thus
must be at least increased to the lower end of the range the signature
is for. By doing so the ability is lost to unseal the resource for
signatures associated with older versions of the UKI, because their
upper end of the range disables access once the counter has been
increased far enough. By carefully choosing the upper and lower end of
the counter range whenever the PCR values for an UKI shall be signed
it is thus possible to ensure that updates can invalidate prior
versions’ access to resources. By placing some space between the upper
and lower end of the range it is possible to allow a controlled level
of fallback UKI support, with clearly defined milestones where
fallback to older versions of an UKI is not permitted anymore.

Example: a hypothetical distribution FooOS releases a regular stream
of UKI kernels 5.1, 5.2, 5.3, … It signs the expected PCR values for
these kernels with a key pair it maintains in a HSM. When signing UKI
5.1 it includes information directed at the TPM in the signed data
declaring that the TPM counter must be above 100, and below 120, in
order for the signature to be used. Thus, when the UKI is booted up
and used for unlocking an encrypted volume the unlocking code must
first increase the counter to 100 if needed, as the TPM will otherwise
refuse unlocking the volume. The next release of the UKI, i.e. UKI 5.2
is a feature release, i.e. reverting back to the old kernel locally is
acceptable. It thus does not increase the lower bound, but it
increases the upper bound for the counter in the signature payload,
thus encoding a valid range 100…121 in the signed payload. Now a major
security vulnerability is discovered in UKI 5.1. A new UKI 5.3 is
prepared that fixes this issue. It is now essential that UKI 5.1 can
no longer be used to unlock the TPM secrets. Thus UKI 5.3 will bump
the lower bound to 121, and increase the upper bound by one, thus
allowing a range 121…122. Or in other words: for each new UKI release
the signed data shall include a counter range declaration where the
upper bound is increased by one. The lower range is left as-is between
releases, except when an old version shall be cut off, in which case
it is bumped to one above the upper bound used in that release.

UKI Generation

As mentioned earlier, UKIs are the combination of various resources
into one PE file. For most of these individual components there are
pre-existing tools to generate the components. For example the
included kernel image can be generated with the usual Linux kernel
build system. The initrd included in the UKI can be generated with
existing tools such as dracut and similar. Once the basic components
(.linux, .initrd, .cmdline, .splash, .dtb, .osrel,
.uname) have been acquired the combination process works roughly
like this:

  1. The expected PCR 11 hashes (and signatures for them) for the UKI
    are calculated. The tool for that takes all basic UKI components
    and a signing key as input, and generates a JSON object as output
    that includes both the literal expected PCR hash values and a
    signature for them. (For all selected TPM2 banks)

  2. The EFI stub binary is now combined with the basic components, the
    generated JSON PCR signature object from the first step (in the
    .pcrsig section) and the public key for it (in the .pcrpkey
    section). This is done via a simple “objcopy” invocation
    resulting in a single UKI PE binary.

  3. The resulting EFI PE binary is then signed for SecureBoot (via a
    tool such as
    sbsign
    or similar).

Note that the UKI model implies pre-built initrds. How to generate
these (and securely extend and parameterize them) is outside of the
scope of this document, but a related document will be provided
highlighting these concepts.

Protection Coverage of SecureBoot Signing and PCRs

The scheme discussed here touches both SecureBoot code signing and TPM
PCR measurements. These two distinct mechanisms cover separate parts
of the boot process.

Specifically:

  • Firmware/Shim SecureBoot signing covers bootloader and UKI

  • TPM PCR 11 covers the UKI components and boot phase

  • TPM PCR 12 covers admin configuration

  • TPM PCR 15 covers the local identity of the host

Note that this means SecureBoot coverage ends once the system
transitions from the initrd into the root file system. It is assumed
that trust and integrity have been established before this transition
by some means, for example LUKS/dm-crypt/dm-integrity, ideally bound
to PCR 11 (i.e. UKI and boot phase).

A robust and secure update scheme for PCR 11 (i.e. UKI) has been
described above, which allows binding TPM-locked resources to a
UKI. For PCR 12 no such scheme is currently designed, but might be
added later (use case: permit access to certain secrets only if the
system runs with configuration signed by a specific set of
keys). Given that resources measured into PCR 15 typically aren’t
updated (or if they are updated loss of access to other resources
linked to them is desired) no update scheme should be necessary for
it.

This document focuses on the three PCRs discussed above. Disk
encryption and other userspace may choose to also bind to other
PCRs. However, doing so means the PCR brittleness issue returns that
this design is supposed to remove. PCRs defined by the various
firmware UEFI/TPM specifications generally do not know any concept for
signatures of expected PCR values.

It is known that the industry-adopted SecureBoot signing keys are too
broad to act as more than a denylist for known bad code. It is thus
probably a good idea to enroll vendor SecureBoot keys wherever
possible (e.g. in environments where the hardware is very well known,
and VM environments), to raise the bar on preparing rogue UKI-like PE
binaries that will result in PCR values that match expectations but
actually contain bad code. Discussion about that is however outside of
the scope of this document.

Whole OS embedded in the UKI

The above is written under the assumption that the UKI embeds an
initrd whose job it is to set up the root file system: find it,
validate it, cryptographically unlock it and similar. Once the root
file system is found, the system transitions into it.

While this is the traditional design and likely what most systems will
use, it is also possible to embed a regular root file system into the
UKI and avoid any transition to an on-disk root file system. In this
mode the whole OS would be encapsulated in the UKI, and
signed/measured as one. In such a scenario the whole of the OS must be
loaded into RAM and remain there, which typically restricts the
general usability of such an approach. However, for specific purposes
this might be the design of choice, for example to implement
self-sufficient recovery or provisioning systems.

Proposed Implementations & Current Status

The toolset for most of the above is already implemented in systemd and related projects in one way or another. Specifically:

  1. The
    systemd-stub
    (or short: sd-stub) component implements the discussed UEFI stub
    program

  2. The
    systemd-measure
    tool can be used to pre-calculate expected PCR 11 values given the
    UKI components and can sign the result, as discussed in the UKI
    Image Generation section above.

  3. The
    systemd-cryptenroll
    and
    systemd-cryptsetup
    tools can be used to bind a LUKS2 encrypted file system volume to a
    TPM and PCR 11 public key/signatures, according to the scheme
    described above. (The two components also implement a “recovery
    key
    ” concept, as discussed above)

  4. The
    systemd-pcrphase
    component measures specific words into PCR 11 at the discussed
    phases of the boot process.

  5. The
    systemd-creds
    tool may be used to encrypt/decrypt data objects called
    “credentials” that can be passed into services and booted systems,
    and are automatically decrypted (if needed) immediately before
    service invocation. Encryption is typically bound to the local TPM,
    to ensure the data cannot be recovered elsewhere.

Note that
systemd-stub
(i.e. the UEFI code glued into the UKI) is distinct from
systemd-boot
(i.e. the UEFI boot loader than can manage multiple UKIs and other
boot menu items and implements automatic fallback, an interactive menu
and a programmatic interface for the OS among other things). One can
be used without the other – both sd-stub without sd-boot and vice
versa – though they integrate nicely if used in combination.

Note that the mechanisms described are relatively generic, and can be
implemented and be consumed in other software too, systemd should be
considered a reference implementation, though one that found
comprehensive adoption across Linux distributions.

Some concepts discussed above are currently not
implemented. Specifically:

  1. The rollback protection logic is currently not implemented.

  2. The mentioned measurement of the root file system volume key to PCR
    15 is implemented, but not merged into the systemd main branch yet.

Glossary

TPM

Trusted Platform Module; a security chip found in many modern
systems, both physical systems and increasingly also in virtualized
environments. Traditionally a discrete chip on the mainboard but today
often implemented in firmware, and lately directly in the CPU SoC.

PCR

Platform Configuration Register; a set of registers on a TPM that
are initialized to zero at boot. The firmware and OS can “extend
these registers with hashes of data used during the boot process and
afterwards. “Extension” means the supplied data is first
cryptographically hashed. The resulting hash value is then combined
with the previous value of the PCR and the combination hashed
again. The result will become the new value of the PCR. By doing this
iteratively for all parts of the boot process (always with the data
that will be used next during the boot process) a concept of
Measured Boot” can be implemented: as long as every element in the
boot chain measures (i.e. extends into the PCR) the next part of the
boot like this, the resulting PCR values will prove cryptographically
that only a certain set of boot components can have been used to boot
up. A standards compliant TPM usually has 24 PCRs, but more than half
of those are already assigned specific meanings by the firmware. Some
of the others may be used by the OS, of which we use four in the
concepts discussed in this document.

Measurement

The act of “extending” a PCR with some data object.

SRK

Storage Root Key; a special cryptographic key generated by a TPM
that never leaves the TPM, and can be used to encrypt/decrypt data
passed to the TPM.

UKI

Unified Kernel Image; the concept this document is about. A
combination of kernel, initrd and other resources. See above.

SecureBoot

A mechanism where every software component involved in the boot
process is cryptographically signed and checked against a set of
public keys stored in the mainboard hardware, implemented in firmware,
before it is used.

Measured Boot

A boot process where each component measures (i.e., hashes and extends
into a TPM PCR, see above) the next component it will pass control to
before doing so. This serves two purposes: it can be used to bind
security policy for encrypted secrets to the resulting PCR values (or
signatures thereof, see above), and it can be used to reason about
used software after the fact, for example for the purpose of remote
attestation.

initrd

Short for “initial RAM disk”, which – strictly speaking – is a
misnomer today, because no RAM disk is anymore involved, but a tmpfs
file system instance. Also known as “initramfs”, which is also
misleading, given the file system is not ramfs anymore, but tmpfs
(both of which are in-memory file systems on Linux, with different
semantics). The initrd is passed to the Linux kernel and is
basically a file system tree in cpio archive. The kernel unpacks the
image into a tmpfs (i.e., into an in-memory file system), and then
executes a binary from it. It thus contains the binaries for the first
userspace code the kernel invokes. Typically, the initrd’s job is to
find the actual root file system, unlock it (if encrypted), and
transition into it.

UEFI

Short for “Unified Extensible Firmware Interface”, it is a widely
adopted standard for PC firmware, with native support for SecureBoot
and Measured Boot.

EFI

More or less synonymous to UEFI, IRL.

Shim

A boot component originating in the Linux world, which in a way
extends the public key database SecureBoot maintains (which is under
control from Microsoft) with a second layer (which is under control of
the Linux distributions and of the owner of the physical device).

PE

Portable Executable; a file format for executable binaries,
originally from the Windows world, but also used by UEFI firmware. PE
files may contain code and data, categorized in labeled “sections”

ESP

EFI System Partition; a special partition on a storage
medium that the firmware is able to look for UEFI PE binaries
in to execute at boot.

HSM

Hardware Security Module; a piece of hardware that can generate and
store secret cryptographic keys, and execute operations with them,
without the keys leaving the hardware (though this is
configurable). TPMs can act as HSMs.

DEK

Disk Encryption Key; an asymmetric cryptographic key used for
unlocking disk encryption, i.e. passed to LUKS/dm-crypt for activating
an encrypted storage volume.

LUKS2

Linux Unified Key Setup Version 2; a specification for a superblock
for encrypted volumes widely used on Linux. LUKS2 is the default
on-disk format for the cryptsetup suite of tools. It provides
flexible key management with multiple independent key slots and allows
embedding arbitrary metadata in a JSON format in the superblock.

Thanks

I’d like to thank Alain Gefflaut, Anna Trikalinou, Christian Brauner,
Daan de Meyer, Luca Boccassi, Zbigniew Jędrzejewski-Szmek for
reviewing this text.

The RISC Deprogrammer

Post Syndicated from original https://blog.erratasec.com/2022/10/the-risc-deprogrammer.html

I should write up a larger technical document on this, but in the meanwhile is this short (-ish) blogpost. Everything you know about RISC is wrong. It’s some weird nerd cult. Techies frequently mention RISC in conversation, with other techies nodding their head in agreement, but it’s all wrong. Somehow everyone has been mind controlled to believe in wrong concepts.

An example is this recent blogpost which starts out saying that “RISC is a set of design principles”. No, it wasn’t. Let’s start from this sort of viewpoint to discuss this odd cult.

What is RISC?

Because of the march of Moore’s Law, every year, more and more parts of a computer could be included onto a single chip. When chip densities reached the point where we could almost fit an entire computer on a chip, designers made tradeoffs, discarding unimportant stuff to make the fit happen. They made tradeoffs, deciding what needed to be included, what needed to change, and what needed to be discarded.

RISC is a set of creative tradeoffs, meaningful at the time (early 1980s), but which were meaningless by the late 1990s.

The interesting parts of CPU evolution are the three decades from 1964 with IBM’s System/360 mainframe and 2007 with Apple’s iPhone. The issue was a 32-bit core with memory-protection allowing isolation among different programs with virtual memory. These were real computers, from the modern perspective: real computers have at least 32-bit and an MMU (memory management unit).

The year 1975 saw the release of Intel 8080 and MOS 6502, but these were 8-bit systems without memory protection. This was at the point of Moore’s Law where we could get a useful CPU onto a single chip.

In the year 1977 we saw DEC release it’s VAX minicomputer, having a 32-bit CPU w/ MMU. Real computing had moved from insanely expensive mainframes filling entire rooms to less expensive devices that merely filled a rack. But the VAX was way too big to fit onto a chip at this time.

The real interesting evolution of real computing happened in 1980 with Motorola’s 68000 (aka. 68k) processor, essentially the first microprocessor that supported real computing.

But this comes with caveats. Making microprocessor required creative work to decide what wasn’t included. In the case of the 68k, it had only a 16-bit ALU. This meant adding two 32-bit registers required passing them twice through the ALU, adding each half separately. Because of this, many call the 68k a 16-bit rather than 32-bit microprocessor.

More importantly, only the lower 24-bits of the registers were valid for memory addresses. Since it’s memory addressing that makes a real computer “real”, this is the more important measure. But 24-bits allows for 16-megabytes of memory, which is all that anybody could afford to include in a computer anyway. It was more than enough to run a real operating system like Unix. In contrast, 16-bit processors could only address 64-kilobytes of memory, and weren’t really practical for real computing.

The 68k didn’t come with a MMU, but it allowed an extra MMU chip. Thus, the early 1980s saw an explosion of workstations and servers consisting of a 68k and an MMU. The most famous was Sun Microsystems launched in 1982, with their own custom designed MMU chip.

Sun and its competitors transformed the industry running Unix. Many point to IBM’s PC from 1982 as the transformative moment in computer history, but these were non-real 16-bit systems that struggled with more than 64k of memory. IBM PC computers wouldn’t become real until 1993 with Microsoft’s Windows NT, supporting full 32-bits, memory-protection, and pre-emptive multitasking.

But except for Windows itself, the rest of computing is dominated by the Unix heritage. The phone in your hand, whether Android or iPhone, is a Unix computer that inherits almost nothing from the IBM PC.

These 32-bit Unix systems from the early 1980s still lagged behind DEC’s VAX in performance. The VAX was considered a mini-supercomputer. The Unix workstations were mere toys in comparison. Too many tradeoffs were made in order to fit everything onto a single chip, too many sacrifices made.

Some people asked “What if we make different tradeoffs?

Most people thought the VAX was the way of the future, and were all chasing that design. The 68k CPU was essentially a cut down VAX design. But history had anti-VAX designs that worked very differently, notably the CDC 6600 supercomputer from the 1960s and the IBM 801/ROMP processor from the 1970s.

It’s not simply one tradeoff, but a bunch of inter-related tradeoffs. They snowball — each choice you make changes the costs-vs-benefit analysis of other choices, changing them as well.

This is why people can’t agree upon a single definition of RISC. It’s not one tradeoff made in isolation, but a long list of tradeoffs, each part of a larger scheme.

In 1987, Motorola shipped its 68030 version of the 68k processor, chasing the VAX ideal. By then, we had ARM, SPARC, and MIPS processors that significantly outperformed it. Given a budget of roughly 100,000 transistors allowed by Moore’s Law of the time, the RISC tradeoffs were better than VAX-like tradeoffs.

So really, what is RISC?

Let’s define things in terms of 1986, comparing the [ARM, SPARC, MIPS] processors called “RISC” to the [68030, 80386] processors that weren’t “RISC”. They all supported full 32-bit processing, memory-management, and preemptive multitasking operating systems like Unix.

The major ways RISC differed were:

  • fixed-length instructions (32-bits or 4-bytes each)
  • simple instruction decoding
  • horizontal vs. vertical microcode
  • deep pipelines of around 5 stages
  • load/store aka reg-reg
  • simple address modes
  • compilers optimized code
  • more registers

If you are looking for the one thing that defines RISC, it’s the thing that nobody talks about: horizontal microcode.

The VAX/68k/x86 architecture decoded external instructions into internal control ops that were pretty complicated, supporting such things as loops. Each external instruction executed an internal microprogram with a variable number of such operations.

The classic RISC worked differently. Each external instruction decoded into exactly 4 internal ops. Moreover, each op had a fixed purpose:

  1. read from two registers into the ALU (arithmetic-logic unit)
  2. execute a math operation in the ALU
  3. access memory (well, the L1 cache)
  4. write results back into one register

(This explanation has been fudged and simplified, btw).

This internal detail was expressed externally in the instruction set, simplifying decoding. The external instructions specified two registers to read, an ALU opcode, and one register to write. All of this was fit into a constant 32-bits. In contrast, the [68k/x86/VAX] model meant a complex decoding of instructions with a large ROM containing microprograms.

Roughly half (50%) of the 68000’s transistors contained this complex decoding logic and ROM. In contrast, for RISC processors, it was closer to 1%. All those transistors could be dedicated to other things. See how tradeoffs snowball? Saving so many transistors involved in instruction decoding meant being able to support other features elsewhere. It’s not clear this is a benefit, however. This meant that RISC needed multiple instructions to do the same thing as a single [68k/x86/VAX] instruction.

This meant instructions could be deeply pipelined. Instructions could be overlapped. When reading registers for the current instruction, we can simultaneously be fetching the next, and performing the ALU calculation on the previous instruction. The classic RISC pipeline had 5 stages (the 4 mentioned above plus 1 for fetching the next instruction). Each clock cycle would execute part of 5 instructions simultaneous, each at a different stage in the pipeline.

This was called scalar operation, In previous processor, it would take a variable number of clock cycles for an instruction to complete. In RISC, every instruction had 5 clock cycle latency from beginning to end. And since execution was overlapped/pipelined, executing 5 instructions at a time, the throughput was one instruction per clock cycle.

All CPUs are pipelined to some extent, but they need complex interlocks to prevent things from colliding with each other, such as two pipelined instructions trying to read registers at the same time. RISC removed most of those interlocks, by strictly regulation what an instruction could do in each stage of the pipeline. Removing these interlocks reduced transistor count and sped things up. This could be one possible definition of RISC that you never hear of: it got rid of all these interlocks found in other processors.

Some pipeline conflicts were worse. Because pipelining, the results of an instruction won’t be available until many clock cycles later. What if one instruction writes its results to register #5 (r5), and the very next instruction attempts to read from register #5 (r5)? It’s too soon, it has to wait more clock cycles for the result.

The answer: don’t do that. Assembly language programmers need to know this complication, and are told to simply not write code that does this, because then the program won’t work.

This was anathema of the time. Throughout history to this point, each new CPU architecture also had a new operating-system written in assembly language, with many applications written in assembly language. Thus, a programmer-friendly assembly language was considered one of the biggest requirements for any new system. Requiring programmers to know such quirks lead to buggy code was simply unacceptable. Everybody knew that programmer-hostile instruction-sets would never work in the market, even if they performed faster and cheaper.

But technology is littered with what everybody knowing being wrong. In this case, by 1980 we had the  C programming language that was essentially a “portable assembly language” and the Unix operating system written in C. The only people who needed to know about a quirky assembly language were the compiler writers. They would take care of all such problems.

That’s why the history lesson above talks about Unix and real computing. Without Unix and C, RISC wouldn’t have happened. An operating-system written in a high-level language was a prerequisite for RISC. It’s as import an innovation as Moore’s Law allowing 100,000 transistors to fit on a chip.

Because of the lack of complex decoding logic, the transistor budget was freed up to support such things as more registers. The Intel x86 architecture famously had 8 registers, while the RISC competitors typically had as many as 32. The limitation was decode space. It takes 5 bits to specify one of 32 possibilities. Given that most every instructions specified two registers to read from and one register to write to, that’s 15 bits, or half of the instruction space, leaving 17 bits for other purposes.

The creators of the RISC, Hennessy and Patterson, wrote a textbook called a “Computer Architecture: A Quantitative Approach“. It’s horrible. It imagines a world where people need to be taught tradeoffs and transistor budgets. But there is no other approach than a quantitative one, it’s like an economics textbook “Economics: A Supply And Demand Approach”. While the textbook has a weird obsession with quantitative theory, it misses non quantitative tradeoffs, like the fact that RISC couldn’t happen without C and Unix. 

Among the snowballing tradeoffs is the load/store architecture, while at the same time, having fewer addressing modes. It’s here that we need to go back and discuss history — what the heck is an “addressing mode“????

In the beginning, computers had only a single general purpose register, called the accumulator. All calculations, like adding two numbers together, involved reading the second value from memory and combining with the first value already in the accumulator. All calculations, whether arithmetic (add, subtract) or logical (AND, OR, XOR) involved one value already in the register, and another value from memory.

Addresses have to be calculated. For example, when accessing elements in a table, we have to take the row number, multiply it by the size of the table, add an offset into the row for desired column, then add all that to the address at the start of the table. Then after calculating this address, we often want to increment the index to fetch the next row.

If the table base address and row index are held in registers, we might get a complex instructions like the following. This calculates and address using two registers r10 and r11, fetches that value from memory, then adds it into register r9.

 ADD r9, [r10 + r11*8 + 4]

Such calculations embedded in the instruction-set were necessary for such early computers. While they had only a single general purpose register (the accumulator), they still had multiple special purpose registers used this way for address calculations. 

For complex computers like the VAX, such address modes imbedded in instructions were no longer necessary, but still desirable. Half the work of the computer is in calculating memory addresses. It’s very tedious for programmers to do it manually, easier when the instruction-set takes care of common memory access patterns (like accessing cells within a table).

This leads us to the load/store issue.

With many registers, we no longer need to read another value from memory (a reg-mem calculation). We can instead perform the calculation using two registers (reg-reg). The VAX had such reg-reg instructions, but programmers still mostly used the reg-mem instructions with the complex address calculations.

RISC changed this. Calculations were now exclusively reg-reg, where math operations like addition could only operate on registers. To add something from memory, you needed first to load it from memory into a register, using a separate, explicit instruction. Likewise, writing back to memory required an explicit store operation.

This architecture can be called either reg-reg or load/store, with the second name being more popular.

With RISC, addressing modes were still desirable, but now they applied to only the two load and store instructions.

The available addressing modes were constrained by the limited RISC pipeline and limited 32-bit fixed-length instructions. Since the pipeline allowed for the reading of two registers at the start, adding two registers together to form the address was allowed. The example shown above was too complex, though.

What you are supposed to be reading from all of this is that all of these tradeoffs are linked. Each decision that diverges from the ideal VAX-like architecture snowballed into other decisions that drifted further and further from this ideal, until what we had was something that looked nothing like a VAX.

The upshot of these decisions was being able to reduce a 32-bit MMU CPU into roughly a single chip because it needed fewer transistors, while at the same time performing much faster. It required maybe twice as many instructions to perform the same tasks (mostly due to needing more complex address calculations due to lack of addressing modes), but performed them at maybe 5 times faster, for a significant speed up.

At the time, the VAX was the standard benchmark target. When Sun shipped it’s first SPARC RISC systems (the Sun-4), they benchmarked about twice as fast as the latest VAX systems, while being considerably cheaper.

The end of RISC

By the late 1980s, everybody knew that RISC was the future. Sure, Intel continued with its x86 and Motorola with it’s 68000, but that’s because the market wanted backwards compatibility with legacy instruction-sets. Both attempted to build their own RISC alternatives, but failed. When backwards compatibility wasn’t required, everybody created RISC processors, because for 32-bit MMU real computing, they were  better. And everybody knew it.

But of course, everybody was eventually wrong. Even as early as the 80486 in 1989, Intel was converting the innards of the processor into something that looked more RISC-like.

The nail in the coffin came in 1995 with Intel’s Pentium Pro processor that supported out-of-order (or OoO) processing. Again, it wasn’t really a new innovation. Out-of-order instructions first appeared on 1960s era supercomputers from CDC and IBM. This was the first time that transistor budgets allowed it to be practically used on single-chip microprocessors.

Transistor budgets were so high that designers no longer had to make basic painful tradeoffs. The decisions necessary trying to cram everything into 100,000 transistors were longer meaningful when you had more than 1-million transistors to work with. Instruction-set decoding requiring 20k transistors is important with small budgets, but meaningless with large budgets.

With OoO, the microarchitecture inside the chip looks roughly the same, regardless if it’s an Intel x86, ARM, SPARC, or whatever.

This was proven in benchmarks. When Intel released its out-of-order Pentium Pro in 1995, it beat all the competing in-order RISC processors on the market.

Everybody was wrong — RISC wasn’t the future, the future was OoO.

One way of describing the Pentium Pro is that it “translates x86 into RISC-like micro-ops“. What that really means is that instead of vertical microcode, it translated things into horizontal, pipelined micro-ops. Most of the typical math operations were split into two micro-ops, one a load/store operation, and the other a reg-reg operation. (Some x86 instructions need even more micro-ops: address calculation, then load/store, then ALU op).

Intel still has an “x86 tax” decoding complex instructions. But in terms of pipeline stages, that tax only applies to the first stage. Typical OoO processors have at least 10 more stages after that. Even RISC instruction-set processors like ARM must translate external instructions into internal micro-ops.

The only significant difference left is the fact that Intel’s instructions are variable length. The fixed length instructions of RISC means that multiple can be fetched at once, and decoded all in parallel. This is impossible with Intel x86, they must at least partially be decoded serially, one before the next. You don’t know where the next instruction starts until you’ve figured out the length of the current instruction.

Intel and AMD find crafty ways to get around this. For example, AMD has often put hints in its instruction cache (L1I) to so that decoders can know the length of instructions. Intel has played around with “loop caches” (so-called because they are most useful for loops) that track instructions after they’ve been decoded, so they don’t need to be decoded again.

The upshot is that for most code, there’s no inherent difference between x86 and RISC, they have essentially the same internal architecture for out-of-order (OoO) processors. No instruction-set has an inherent advantage over the other.

And it’s been that way since 1995.

I mention this because bizarrely this cult has persisted for the last 30 years after OoO replaced RISC for high-end real computers. It ceased being a useful technical distinction, so what are techies still discussing it?

They persist in believing dumb things, for which no amount of deprogramming is possible. For example, they look at mobile (battery powered) devices and note that they use ARM chips to conserve power. They make the assumption that there must be some sort of inherent power-efficiency advantage.

This isn’t true. These chips consume less power by simply being slower. Fewer transistors mean less power consumption. This meant while desktops/servers used power-hungry OoO processors, mobile phones went back to the transistor budgets of yesteryear, meaning back to in-order RISC.

But as Moore’s Law turned, transistors got smaller, to the point where even mobile phones got OoO chips. They use clever tricks to keep that OoO chip powered down most of the time, often including an in-order chip that runs slower on less power for minor tasks.

We’ve reached the point where mobile and laptops now use the same chips, your MacBook uses (essentially) the same chip as your iPhone, which is the same chip as Apple desktops.

Now Apple’s M1 ARM (and hence RISC) processor is much better at power consumption than it’s older Intel x86 chip, but this isn’t because it’s RISC. Apple did a good job at analyzing what people do on mobile devices like laptops and phones and optimized for that. For example, they added a lot of great JavaScript features, cognizant of the ton of online and semi-offline apps that are written in JavaScript. In contrast, Intel attempts to optimize a chip simultaneously for laptops, desktops, and servers, leading poorly optimizations for laptops.

Apple also does crazy things like putting a high end GPU (graphics processor) on the same chip. This has the effect of making their M1 ARM CPU crazy good for desktops for certain applications, those requiring the sorts of memory-bandwidth normally needed by GPUs.

But overall, x86 chips from AMD and Intel are still faster on desktops and servers.

In addition to the fixed-length instructions providing a tiny benefit, ARM has another key advantage, but it has nothing to do with RISC. When they upgraded their instruction-set to support 64-bit instead of just 32-bit, they went back and redesigned it from scratch. This allowed them to optimize the new instruction-set for the OoO pipeline, such as removing some dependencies that slow things down.

This was something that Intel couldn’t do. When it came time to support 64-bit, AMD simply extended the existing 32-bit instructions. A long sequence of code often looks identical between the 32-bit and 64-bit versions of the x86 instruction-sets, whereas they look completely different on ARM 32-bit vs. 64-bit.

What about RISC-V and ARM-on-servers?

We’ve reached the point in tech where the instruction-set doesn’t matter. It’s not simply that code is written in high-level language. It’s mostly that micro-architectural details have converged.

Take byte-order, for example. Back in the 1980s, most of the major CPUs in the world were big-endian, while Intel bucked the trend being little-endian. The reason is that some engineer made a simple optimization back when the 8008 processor was designed for terminals, and because of backwards compatibility, the poor decision continues to plague x86 today.

Except when it annoys programmers debugging memory dumps, byte-order doesn’t matter. Therefore, all the RISC processors allowed a simple bit to be set to switch processors from big-endian to little-endian mode.

Over time, that has caused everyone to match Intel’s little-endianess, driven primarily by Linux. The kernel itself supports either mode, but a lot of drivers depend upon byte-order, and user-mode programs developed on x86 sometimes have byte-order bugs. As it was ported to architectures like ARM or PowerPC, most of the time it was done in little-endian mode. (You can get PowerPC Linux in big-endian, but the preference is little-endian, because drivers).

The same effect happens even in things that aren’t strictly CPU related, like memory and I/O. The tech stack has converged so that processors look more and more alike except for the instruction-set.

The convergence of architecture is demonstrated most powerfully by Apple’s M1 transition, where they stopped using Intel’s processors in their computers in favor of their custom ARM processor they created for the iPhone.

The MacBook Air M1 looks identical on the outside compared to the immediately preceding x86 MacBook. But more the the point, it performs almost identically running x86 code — it runs x86 code at native x86 speeds but on an ARM CPU. The processors are so similar architecturally that instruction-sets could be converted on the fly — it simply reads the x86 program, converts to ARM transparently on the fly, then runs the ARM version. Previous code translation attempts have incurred massive slowdowns to account for architectural differences, but the M1 cheated by removing any differences that weren’t instruction-set related, allowing smooth translation of the instructions.

Technically, instruction-sets don’t matter, but for business reasons, they still do. Intel and AMD control x86, and prevent others from building compatible processors. ARM lets others build compatible processors (indeed, making no CPUs themselves), but charges them a license fee.

Especially for processors on the low-end, people don’t want to pay license fees.

For that reason, RISC V has become popular. For low-end processors (in-order microcontrollers competing against ARM Cortex Ms) in the 100,000 transistor range, it matters that an instruction-set be RISC. The only free alternative is the aging MIPS. It has annoying quirks, like “delay slots”, which are fixed by RISC V. Since RISC V is an open standard, free of license fees, those designing their own low end processor have adopted it.

For example, nVidia uses RISC V extensively throughout its technology. GPUs contain tiny embedded CPUs to manage things internally. They have ARM licenses, but they don’t want to pay the pennies it would cost for every unit that ARM charges. Likewise, Western Digital (a big hard-drive maker) designed a RISC V core for its drives. 

There are a lot of RISC V fans due to the RISC cult who insist it should go everywhere, but it’s not going anywhere for high-end processors. At the high-end, you are going to pay licensing fees for designs anyway. In other words, while big companies have the resources to design small in-order processors, they don’t have the resources to design big OoO processors, and would therefore buy designs from others.

Amazon’s AWS Graviton is a good example (ARM-based servers). They aren’t licensing the instruction-set from ARM so much as the complete OoO CPU design. They include the ARM cores on a chip of Amazon’s design, having memory, I/O, security features tailored to AWS use cases. Neither the instruction-set architecture or micro-architecture particularly matter to Amazon compared to all the other features of their chips.

Lots of big companies are getting into the custom CPU game, licensing ARM cores. Big tech companies tend to have their own programming language, their own operating systems, their own computer designs, and nowadays their own CPUs. This includes Microsoft, Google, Apple, Facebook, and so on. The advantage of ARM processors (or in the future, possibly RISC V processors) isn’t their RISC nature, or their instruction-sets, but the fact they are big processor designs that others can included with their own chips. There is no inherent power efficiency or speed benefit — only the business benefit.

Conclusion

This blogpost is in reaction to that blogpost I link above. That writer just recycles old RISC rhetoric of the past 30 years, like claiming it’s a “design philosophy”. It, it was a set of tradeoffs meaningful to small in-order chips — the best way of designing a chip with 100,000 transistors.

The term “RISC” has been obsolete for 30 years, and yet this nonsense continues. One reason is the Penisy textbook that indoctrinates the latest college students. Another reason is the political angle, people hating whoever is dominant (in this case, Intel on the desktop). People believe in RISC, people evangelize RISC. But it’s just a cult, it’s all junk. Any conversation that mentions RISC can be improved by removing the word “RISC”.

OoO has replaced RISC as the dominant architecture for CPUs, and it did so in 1995, and ever since then, the terminology “RISC” is obsolete. The only thing you care about when looking at chips is whether it’s an in-order design or an out-of-order design. Well, that’s if you care about theory. If you care about practice, you care about whether it supports your legacy tooling and code. In the real world, whether you use x86 or ARM or MIPS or PowerPC is simply because of legacy market conditions. We still launch rockets to Mars using PowerPC processors because that’s what the market for radiation-hardened CPUs has always used.

За икономиката

Post Syndicated from original http://www.gatchev.info/blog/?p=2505

Преди малко драснах един коментар в една социална мрежа, на тема икономика. След това реших, че може да е ценно да го пусна и тук. Не че не съм го писал и преди. Но някои хора схващат по-трудно, така че трябва да им се повтаря повече.


Икономиката не е нечии празни приказки, а е наука точно както е наука физиката или пък генетиката. Законите ѝ са също така реални и непробиваеми, както са физичните закони.

(Да, наоколо е пълно с идеолози, които се опитват да пробутват идеологически теории за икономически. Това не прави тези теории повече икономически и по-малко идеологически, точно както геоцентричната теория за Слънчевата система не е накарала Слънцето да се върти около Земята. Който вярва на лъжата, че те са реалност, а не идеология, го прави за своя сметка.)

Икономическият цикъл може да бъде описан много просто (ако и частично): кръг на производство и потребление, и кръг на обменни средства. Двата се „въртят“ в противоположна посока и се захранват един друг.

Кръг на производство: Налични стоки и услуги биват потребявани. В процеса на това потребление се създават материали, стоки, услуги, работна сила и т.н., които биват влагани в производство. То създава определени блага – стоки, услуги и т.н., които отиват за потреблението.

Кръг на обменни средства: За да получат достъп до стоките и услугите, потребителите им дават срещу тях обменни средства (напр. пари). Производителите използват тези обменни средства, за да купят материалите, стоките, услугите, работната сила и т.н., които биват влагани в производството.

Ключът в картинката е, че процесът на производство може да създава повече продукт, отколкото потребява. Благодарение на това икономиката може да расте, населението като цяло да богатее и т.н. Дали реално ще го прави зависи от няколко неща. Ключовото от тях е силната конкуренция – без нея няма стимул за ефективност, независимо от празните приказки и лъжите по въпроса.

За да работи цялата схема и да създава плюс, са нужни две условия. Едното е максимална свобода на процеса на производство, за да бъде той колкото се може по-ефективен. Другото е преразпределяне на обменните средства (парите) така, че достатъчен процент от тях да са у потребителите, за да могат те да купят произведените блага и да не се спира процесът.

Първото условие звучи на болните от идеология на главния мозък много дясно. Второто им звучи много ляво. В реалността нито първото е дясно, нито второто е ляво. Те са просто необходимости, за да работи икономическата машина. Точно както сипването на бензин, подаването на въздух и отвеждането на изгорелите газове са необходимости, за да работи двигател с вътрешно горене.

Спрете ли едно от тях, колкото и да е идеологически „неправоверно“, двигателят ще спре да работи, колкото и останалите да са идеологически „неопровержими“. Може да съм в екстаз от идеята за двигател с вътрешно горене, който работи, без да консумира гориво, и да съм твърдо решен, че по-скоро ще умра, но няма да му сипя бензин. Какво ще стане – двигателят ще заработи без бензин или аз ще се окажа очевиден идиот? Отговорете си сами.

Същото е и с машината на икономиката. Махнете ли кое да е от тези две условия, тя ще спре да работи, независимо колко ви харесва идеята. И независимо колко сте убедени, че идеята е вярна, неопровержима, велика, свещена и т.н. И независимо какви и колко велики и доказали се мъдреци са заявили, че номерът ще мине. Тези, които имат акъла да максимизират и двете, ще спечелят конкурса на еволюцията. Тези, които го нямат, ще отпаднат – ще се окажат вече знаете какво.

Това е положението. Избирайте си сами от кои искате да бъдете.

Mourning Wolfgang Denk

Post Syndicated from original https://lwn.net/Articles/912052/

The U-Boot list carries
the sad news
that Wolfgang Denk, the founder of the U-Boot project, has
passed away.

Wolfgang was a pioneer and strong supporter of Open Source, in the
time when Linux for Embedded System started its first steps. In
many occasions he had strong discussions with customers to explain
the advantages of Open Source, and he rejected business contracts
if customer was going against his principles. We will miss him.

Купон с шампанско и и уиски Кафе „Следствието“. Столичните следователи пият в работно време, тръгват си с колите

Post Syndicated from Николай Марченко original https://bivol.bg/%D0%BA%D0%B0%D1%84%D0%B5-%D1%81%D0%BB%D0%B5%D0%B4%D1%81%D1%82%D0%B2%D0%B8%D0%B5%D1%82%D0%BE-%D1%81%D1%82%D0%BE%D0%BB%D0%B8%D1%87%D0%BD%D0%B8%D1%82%D0%B5-%D1%81%D0%BB%D0%B5%D0%B4.html

събота 22 октомври 2022


Над 100 столични следователи и прокурори пиха в работното си време между 15:30 и 17:30 ч. в сградата на Следствения отдел към Софийска градска прокуратура (СГП) в ж.к. Овча купел.…

Ден трети от избора на председател и ролята на Демократична България

Post Syndicated from Bozho original https://blog.bozho.net/blog/3970

За председател е избран е Вежди Рашидов, като най-възрастен народен представител. Възрастта беше единственият критерий, събрал подкрепа. От ДБ нямаше как да подкрепим Рашидов, по ред причини. На председателски съвет сондирахме възможността наша кандидатура да събере подкрепа. Отговорът беше „не“. Бяхме разумни, конструктивни и направихме възможното. Сега парламентът може да започне работа.

Но има една критика към Демократична България за изминалите три дни – че не сме издигнали наш кандидат за председател.

Общата причина за това е, че се фокусирахме върху търсене на решение на безпрецедентен проблем, а не в това да покажем колко подходящи хора имаме за председател.

След като ГЕРБ бяха неспособни да съберат мнозинство, на третия ден нещата бяха зациклили и кандидатура на ДБ може би е изглеждала като възможен изход. Затова тя беше обсъдена на засесание на парламентарната група и Христо Иванов отиде на председателски съвет, където да го предложи. ГЕРБ и БСП са били твърдо против. Т.е. подкрепа нямаше.

Паралелно с това в кулоарите разговаряхме с депутати от ПП и обсъдихме рисковете и плюсовете на наш кандидат, след което Кирил Петков влезе на председателския съвет, за да повдигнв същия въпрос. Втори път е последвал отказ от ГЕРБ и БСП. Т.е. подкрепа стабилно нямаше.

А защо нямаше подкрепа? Защото всеки избор извън този по технически критерий като възраст ще изглежда политически и ще очертае мнозинство. И щяха да последват резонни реакции от типа на „Ее, прегърнаха се“. Ако подкрепата беше само от ГЕРБ (освен от нас и ПП) – „ето я евроатлантическата коалиция“.

Ако и БСП се бяха включили, те пък трябваше да обясняват на своите избиратели защо подкрепят председател, който ще вкара точката за модернизация на армията и оръжие за Украйна и ще блокира връщането на хартиените бюлетини.

Ако въпреки ясната липса на подкрепа бяхме предложили кандидат в зала той очаквано не беше събрал подкрепа, щяхме да нарушим трайното си поведение на конструктивният субект, който в сложна ситуация не търси нищо за себе си и своя тяснопартиен интерес и не прави пиарски ходове, които усложняват ситуацията. А и щяхме да изхлеждаме нелепо.

Тезата, че ГЕРБ и БСП са щели да размислят в зала, като видят какъв хубав кандидат издигаме е наивна и игнорира три дни разговори във всякакви формати. И по-важното – игнорира реалността, че политически избор беше избгяван на всяка цена. Сега мнозинството, избрало Рашидов може да твърди, че е временно мнозинство, което просто е следвало духа на конституцията.

Грешно е да сглобяваме политически (а не технически) мнозинства в такава ситуация, а наш кандидат би довел такъв наратив – и поради това той не би събрал подкрепа.

В този смисъл, поведението на ДПС и ГЕРБ, които само при мириса на мнозинство се озлобиха и започнаха да газят правилника, е грешка – те превърнаха техническото мнозинство в политическо и колкото и да мажат сега, че с предложението за избор на технически критерий Хтисто Иванов, видиш ли, бил предложил Рашидов, грешката е налице и мнозинството им изглежда повече от техническо.

Демократична България, с 20 депутати, през цялото време беше (като каза Цветанка Ризова) перпетуум мобиле за консенсусни предложения. И поставихме работата на парламента и решаването на кризисната ситуация над партийния интерес и пиарските ходове. Защото целта на политиката не са фейсбук лайкове, а постигане на резултати.

Разбирам неудовлетворението от избора на Рашидов. Затова и от ДБ имаше 20 гласа „против“. Но сложната, фрагментирана среда произведе това. Сега предстои в същата тази среда, обогатена от тридневната сага, да опитаме да намираме решения на по-трудни въпроси.

Материалът Ден трети от избора на председател и ролята на Демократична България е публикуван за пръв път на БЛОГодаря.

Officially retiring this…

Post Syndicated from Unknown original https://lcamtuf.blogspot.com/2022/10/officially-retiring-this.html

Thank you for stopping by.

After more than a decade of posting infosec commentary on this blog, I decided to pull the plug. I still publish quite a bit, but I’m less and less inclined to use blogspot.com. For one, the platform just doesn’t seem to be actively maintained; for example, spam issues have gotten so severe that I had to turn off comments a year ago. But I also wanted to write more about other hobbies, and that’s difficult when all the subscribers signed up just for the infosec stuff.

To stay in touch, please subscribe on Substack for weekly long-form articles on a variety of topics. Here’s a sampling of my Substack articles you might enjoy:

Alternatively, you can follow me on Twitter or Mastodon for random hot takes.

Седмицата (17–22 октомври)

Post Syndicated from Светла Енчева original https://toest.bg/editorial-17-22-october-2022/

Седмицата премина в парламентарен абсурдизъм и странна диалогичност на главния прокурор Иван Гешев на фона на непрестанните удари, които Русия нанася върху гражданската инфраструктура и цивилното население на Украйна. Преди изборите се чудехме дали новият парламент ще успее да излъчи правителство, но въображението ни е било бедно, както впрочем и на авторите на Конституцията на България. Народното събрание се спъна още в първата си задача – да избере свой председател, а такъв казус не е предвиден в основния ни закон. През това време пък Бойко Борисов, председател на партията, спечелила най-много гласове на изборите, риташе мачле.

Парламентарната демокрация, която, по думите на Ива Митева от ИТН, „като че се изхаби“, изглежда все по-абсурдистки. В този контекст фактът, че накрая за председател на парламента беше избран неадекватно ръководещият тридневното първо заседание Вежди Рашидов, носител на мутренския приз „главен мултак на републиката“, си изглежда намясто. По-намясто би било само да се избере бездомното куче пред парламента, прочуло се в деня на откриването на 48-мото Народно събрание. А и кучето буквално беше пред-седател, тоест седеше отпред.

Абсурдността обаче не е на самата демокрация, а на политическата ситуация у нас. Затова е добре да не забравяме сериозния принос на ИТН за настоящото положение. Тъкмо партията на Слави Трифонов направи всичко по силите си, тъй щото трите предишни парламента да имат толкова кратък живот, тъканта на политическото да се разпадне в максимална степен и демокрацията да изглежда „изхабена“.

Емилия Милчева

Краят на парламента започна още с началото му, констатира Емилия Милчева в политическия си коментар, очаквано посветен на основната вътрешнополитическа тема тази седмица. В него се проследява първият работен ден на 48-мото Народно събрание и се анализират различните мнозинства в него, които правят работата му още по-трудна. Едни са лагерите „за“ и „против“ подкрепа на Украйна, други са по отношение на корупцията и безконтролната власт на главния прокурор. А последното обяснява необичайната диалогичност на Гешев, която според Емилия издава страх.

Статия, написана съвместно от двама бивши председатели на Съюза на съдиите в България, не се появява всеки ден. Мирослава Тодорова, наказателен съдия в Софийския градски съд, и Калин Калпакчиев, съдия в Софийския апелативен съд, приеха поканата да разяснят за читателите на „Тоест“ що е то възстановително правосъдие, какви са принципите му, защо го има и защо е необходимо да се прилага по-често в травматизирано общество като българското. То е преди всичко „способ да видиш другия като пълноценно човешко същество“. Защото и от двете страни на съдебния процес стоят хора.

Николета Атанасова

В петия епизод на подкаста на Николета Атанасова „Украйна не е загубена: Кризи“ следим две истории. Първата е на украинката Алла – тя идва у нас заедно с дъщеря си, бягайки от бомбардировките в Киев, но четири месеца след началото на войната се завръща в Украйна, за да бъде до мъжа си. Втората история е на Юри, украинец от Мариупол, който изненадващо заминава от България за Москва, оставяйки приятелката си тук. Заплетената лична история на две почти деца, избягали в България от Русия, повдига много въпроси, които надхвърлят частното пространство на героите в нея.

Стефан Русинов

Без важничене Стефан Русинов интервюира Йордан Д. Радичков, чийто последен сборник с разкази „Навалица! Или за 25 часа в град София“ беше отразен преди месец от Зорница Христова в рубриката „По буквите“. Под привидната фриволност на разговора между двамата се крият сериозни теми – за суетата, за това, че „хем сме сами, хем непрекъснато сме заедно“, за „сложнотията на ежедневието, което всеки ден ни удря по муцуните и настоява да се борим с него“. За това, че думите винаги са важни, дори да са просто „дрънкане“.

Стефан Иванов

И отново Йордан Радичков, но не събеседникът на Стефан Русинов, а неговият дядо и автор на „Ние, врабчетата“. В рубриката „На второ четене“ Стефан Иванов ни припомня друга негова книга – „Малки жабешки истории“. Той препоръчва четенето на Радичков в пристъпи на сезонна тъга, а даже и на моментна радост. Както често се случва при детските книги, писателят е вдъхновен от внучката си. Ако има задълбочено академично изследване на флората и фауната в творчеството на Радичков, в него непременно трябва да присъства и глава за жабата, смята Стефан.

Личната ми препоръка този път е кратка, но ми се вижда нужна в настоящата турбулентна ситуация: без паника. И тъй като това беше цитат от Дъглас Адамс, да добавя и – когато тръгвате нанякъде, не си забравяйте хавлията.

Източник

Възстановителното правосъдие – опит за помирение

Post Syndicated from Колектив original https://toest.bg/vuzstanovitelnoto-pravosudie-opit-za-pomirenie/

Възстановителното правосъдие е тема, която не е много позната на широката публика в България, макар че страната ни има традиции в тази насока още от времето след Освобождението. За нас е истинска чест, че Мирослава Тодорова, наказателен съдия в Софийския градски съд, и Калин Калпакчиев, съдия в Софийския апелативен съд, и двамата – бивши председатели на ССБ, се съгласиха да ни разяснят в тази обстойна статия какви са основните принципи на възстановителното правосъдие и как то може да бъде социален регулатор за травматизирани общества с тежка липса на доверие към институциите и между самите хора.


Автори: Мирослава Тодорова, Калин Калпакчиев

В този текст се опитваме да разкажем за основните ценности и принципи на възстановителното правосъдие като шанс не само за очовечаване на традиционното възмездително правосъдие, но и за изграждане на гражданска култура за мирна работа с конфликти без намеса на държавната власт, за участие в дебати по болезнени теми с нагласата да се разбере, а не да се заклейми с ненавист насрещната гледна точка, независимо от дълбокото ни несъгласие с нея.

Възстановителното правосъдие – такова, каквото е създадено от критическата криминология – е преди всичко способ да видиш другия като пълноценно човешко същество. А това означава да приемеш, че си включен в мрежата от норми, които ни правят хора, както казва норвежкият социолог и криминолог проф. Нилс Кристи. Именно тази сърцевина на възстановителното мислене го прави изключително уместен социален регулатор за травматизирани общества с тежка липса на доверие както между хората, така и към собствените им държавни и обществени институции.

Българското общество е такова отдавна – ежедневно на пътни кръстовища между напълно непознати хора се упражнява насилие заради неправилна маневра и неспособност да се овладее гневът и да се постигне мирна саморегулация. А на последните парламентарни избори се видяха дълбоките разломи между социалните групи и критично ниското ниво на доверие, проявено в отказа на голямата част от гражданите с право на глас изобщо да отиде до избирателните секции или в избора на онези 87 635 души (близо 3,5% от гласовете на избирателите), отбелязали в бюлетината „Не подкрепям никого“. Те са поредното тъжно потвърждение за социална травматичност.

Нуждата да се обърне посоката, да се пречупи тенденцията изисква всеки от позицията на собствения си личен или професионален опит да търси и споделя средства за укрепване на способността за съпричастие, за осъзнаване и обществена консолидация. Затова и ние, през призмата на своята опитност, се осмеляваме да ви занимаваме с възстановителното правосъдие.

Движението за възстановително правосъдие се разраства след Втората световна война като отговор на провала на традиционното правосъдие в модерната държава да спре нечовешките зверства, извършени от формално законните нацистки режими. Правото е нормативна система, която има за цел да регулира обществените отношения чрез въвеждане на общовалидни и абстрактни правила за поведение, чието спазване се гарантира с държавна принуда. Целта му е да установи правна сигурност и върховенство на правото, което постига равенство на всички граждани пред закона.

Тази цел е от първостепенна важност за функционирането на демократичните държави. Тя обаче лесно може да бъде подменена, ако на правната форма се придаде съдържание, което не е насочено към постигане на справедливост. Така след трагичната равносметка на факторите и причините за индустриализираната система за убийства в концлагерите и за законното експроприиране на собствеността на „не-арийците“, юристите, криминолозите и другите социални учени търсят средства, които да възпрепятстват отчуждаването на правото от неговото основание и да укрепват системата от мерки за защита на човешкото достойнство. Този стремеж е благодатната почва за интензивното развитие на доктрината за човешките права и на възстановителното правосъдие.

За разлика от традиционното правосъдие, възстановителното не търси унифициране и не изхожда от общи типизирани положения. То винаги е конкретно, фокусирано върху особеностите и силите на определения човек, съсредоточено е в личната му история, не се основава на принуда, способства за създаване на ред в отношенията на хората в общността и не разчита на никакво покровителство и институционализирана сила. Тоест не само че не изисква, но и не допуска влиянието на външен авторитет и не толерира нагоните за сближаване с властта.

Последната особеност представлява по естеството си силен антикорупционен фактор. Изграждането на общности от взаимнозависими един от друг граждани прави безобразията видими, а същността на конфликтите – отчетлива. В такава реалност всяка злоупотреба с власт вече не може лесно „да остане скрита в неясни компромиси“ (по Нилс Кристи). Възстановителното правосъдие отваря пространство за хората да изнесат цялата истина за събитията, в които те са централните персонажи, без професионални посредници.

На този принцип са създадени Комисиите за истина и помирение в редица държави с цел да се разкрие истината за различни форми на потиснически политически режими в период на преход на обществата към демократична форма на публично управление. Такива комисии възникват в държави с дългогодишно изключване на социални групи и етническа дискриминация, характерни например за политиката на апартейд спрямо чернокожите в ЮАР, спрямо инуитите в Канада, спрямо аборигените в Австралия.

Така например Комисията в ЮАР е създадена, след като се стига до убеждението, че наказването на извършителите на престъпления не би било достатъчно за постигане на социален мир и за преодоляване на травмите от дискриминацията и дългогодишното насилие, защото в почти всеки дом е имало жертва или насилник и конфликтът помежду им би бил взривоопасен. На формите на социалното изключване в миналото е безсмислено да се отговаря чрез реципрочно възмездие – с нови форми на социално изключване. Затова и преамбюлът на новата Конституция на ЮАР започва с изразената готовност да се разбере миналото, за да може общността да продължи напред: „Ние, хората на Южна Африка, признаваме несправедливостите на своето минало…“

Още една съществена разлика с традиционното правосъдие е, че възстановителното включва в процеса на осъществяването си активно участие на страните в конфликта и крайното решение се приема от тях не като „спуснато“ по вертикала на държавната власт, а като лично постижение – достигнато въз основа на собствено усилие и поемане на отговорност.

Това директно кореспондира с някои от основните липси и нужди на българската ситуация. В България съществува проблем с доверието в правосъдието. Генезисът на този проблем е сложен и произтича от множество фактори – правен нихилизъм, понякога стимулиран от изпълнителната власт; неразрешени структурни проблеми на съдебната власт; недостатъчно развита правна култура; историческа обремененост, произтичаща от продължителни периоди без реално разделение на властите, политически плурализъм и свобода на словото и др.

Всички тези фактори водят до усещане за липса на справедливост у част от гражданите, което от своя страна се превръща в значим фактор за дезинтеграцията на обществото. В резултат се провокира разделение между хората, което поради ниското доверие помежду им лесно прераства в ненавист, дори във физическа агресия. Формира се среда, в която гражданите привикват да нарушават правилата, без да очакват да носят отговорност под каквато и да било форма.

Тъкмо заради същностните си различия с традиционното правосъдие възстановителното правосъдие може да се превърне в ефективно средство за преодоляването на недоверието в съдебната власт. Действително всяко правосъдие би следвало да е изградено върху ценностния императив за постигане на справедливост, тъй като от това произтича неговата легитимност.

Но до справедливия завършек на традиционния съдебен процес се стига по пътя на формални процедури, в които засегнатите лица с процесуални средства реконструират тази истина, която законът определя за „относима“. Не всякога обаче относимите към правната норма факти пресъздават изчерпателната истина, от чието възстановяване и оповестяване често засегнатите хора имат първостепенна необходимост. В този смисъл невинаги традиционното правосъдие е достатъчно, за да се възстановят накърнените социални връзки и да се постигне така необходимото разбиране на случилото се.

Тази „недостатъчност“ на традиционното правосъдие, разбира се, не омаловажава неговата първостепенна значимост за установяване на правовата държава, която вече изтъкнахме. Но осъзнатите му ограничения показват, че системите за социален контрол (за постигне на социален мир и обществено благополучие) имат нужда от създаване на такива мрежи от взаимозависимости между гражданите, които не се основават на власт и подчинение, не разчитат на санкция от страна на държавната власт.

Научни аргументи за осъзнаването на тази необходимост се развиват в криминологията, в частност – в критическата криминология, защото възстановителното правосъдие като едно от средствата за създаване на споена общност от зависими един от друг граждани е в основата на ефективната и трайна превенция на престъпността.

Макар обичайно възстановителното и традиционното възмездително правосъдие да се разглеждат в опозиция, те неминуемо си влияят взаимно. Успешните системи за социален контрол върху факторите, генериращи престъпност, създават ситуации, в които е възможно обикновеният човек да е ангажиран в процеса и да е слушан като най-големия експерт за живота си.

В основополагащата лекция на проф. Нилс Кристи „Конфликтите като собственост“ се изяснява важността на конфликтите за обществото и се разсейва предразсъдъкът, че конфликтите са вредни и опасни. Напротив, обяснява проф. Кристи, в силно индустриализираните общества вътрешните конфликти не са много, те са дори твърде малко. А социалните системи следва да бъдат устроени така, че да подхранват конфликтите и да ги правят видими, като в същото време професионалистите бъдат възпрени да монополизират тяхното разрешаване и се възвърне правото на жертвите на престъпления да участват в разрешаването на конфликтите, които ги засягат.

Затова ефективно функциониращото традиционно правосъдие, което разбира заложените си по дефиниция ограничения, оставя достатъчно широко поле за включване на алтернативни форми. Възстановителните подходи не застрашават целите на традиционното наказателно правосъдие, защото, ако се използват разумно и хуманно, те могат да способстват за пълноценно постигане на целите на наказанието, да разширят и увеличат потенциала на съществуващата правосъдна система. Стига да се справят с основното предизвикателство за правосъдието, основано на личното участие – да се намерят начини за ефективно ангажиране на гражданите и да се осигури пълноценна защита на правата и законните интереси както на пострадалите, така и на нарушителите.

Критическата криминология стига до извода, че колкото и усилено да се демократизира правосъдието, това не е достатъчно, за да не се повтори крахът, ако не се намерят средства и начини за овластяване на хората. Това е така, защото, колкото повече човекът е лишен от отговорност, а тя е поставена в ръцете на „властта“ и експертите (включително съдебните), толкова по-силно той реагира с безотговорност, а това се превръща в най-силния криминогенен фактор и заплаха за трайния мир.

Програмите за възстановително правосъдие са основани на водещия принцип, че престъпното поведение не само нарушава закона, но и уврежда пострадалите и общността. Ето защо се изисква винаги когато е възможно, в процеса по възстановяване след увреждането да бъде въвлечен както нарушителят, така и засегнатите страни – не само пострадалият, а и останалите хора, които като част от съответната общност (квартал, училище, работно място) са поставени в опасност или е накърнена сигурността им. И в същото време да се осигурява необходимата подкрепа на всички замесени, приоритетно – на жертвата.

Затова в някои случаи програмите спомагат и за изграждането и развитието на местни общности, което е особено актуално в нашия национален контекст, доколкото от десетилетия сме свидетели на рушащи се и изчезващи общностни структури на различни нива – в населените места, в училищата, в професионалните среди. Възстановителните програми насърчават толерантността и готовността за лично участие, за изграждане на уважение към различията и за създаването на отговорни обществени практики.

Характерно за възстановителните подходи е, че те не следват формално предписани процедури и могат да се адаптират според нуждите на страните, участващи в конфликта. Най-същественото е, че всички възстановителни практики и програми включват под някаква форма диалог между жертвата и извършителя, както и между останалите засегнати от конфликта представители на семейната, кварталната, училищната, професионалната и т.н. общност.

Голяма част от възстановителните форми са вдъхновени от съществуващи от столетия обичайни практики на местното население. Така например маорите (местното население в Нова Зеландия) използват за разрешаване на конфликтите в общността различни видове кръгови срещи, които включват жертвата, извършителя и членове на техните семейства и на близкия им приятелски кръг – тоест лица, на които те имат доверие. Тази възстановителна форма сега се нарича фамилна конференция. Тя се изразява в поредица от срещи разговори, в които участниците обсъждат какво точно се е случило, какво са почувствали жертвата и извършителят, какви са моралните и материалните вреди, как да се възстановят вредите и отношенията между засегнатите.

Възстановителните кръгове се подпомагат от доброволец, който не е професионалист, но е обучен най-общо да улеснява срещата и да подпомага участниците сами да стигнат до решение, без да ги напътства и да взема отношение по случая. Посредникът помирител трябва да проведе предварителни поверителни разговори с жертвата, извършителя и техните близки. При срещите в кръг правилата обичайно включват няколко прости условия: всеки има право да говори, като дава знак; думата се дава от координиращия помирител; всички се изслушват и не се прекъсват; участието е доброволно и във всеки момент може да бъде оттеглено; решението трябва да бъде взето и възприето от всички.

Друга популярна възстановителна форма е помирителната среща между жертвата и извършителя. Тя също се подпомага от доброволец помирител, който е обучен да спазва базисните правила на възстановителните срещи, да насочва и да следи за риск от злоупотреби и увреждане на участниците, но не и да изземва решението на конфликта от самите страни. В случаите, в които жертвата отказва да се включи в срещата, има възможност за участие на т.нар. сурогатна жертва – пострадал от подобно правонарушение, който се съгласява да говори с извършителя и така да му помогне да осъзнае последиците и вредите от извършеното.

Това показва и нещо друго, което е от особено значение за възстановителните практики: не е важно на всяка цена да се постигне решение на конфликта, а да се помогне на участниците да разберат какво се е случило, да приемат неговите последици и да продължат да живеят с тях, като така сложат основите на бъдещи мирни взаимоотношения.

Често възстановителното правосъдие се прилага посредством съществуващи местни норми – споменахме за Нова Зеландия и възприетите практики на маорите; друг пример е Канада, която стъпва върху обичайните правила на местното коренно население.

България също има традиции в тази насока. След Освобождението са функционирали помирителните (полюбовни съдилища), които са следвали вековната традиция на старейските съвети. Помирителните съдилища са разглеждали единствено граждански спорове и наказателни дела по тъжба на пострадалия, по които страните могат да постигнат спогодба, а също и дела за настойничество. Съдът не е бил ограничен от никакви процесуални форми и правила, а се е ръководел от обичая и се съобразявал с исканията на страните. Решенията му са имали сила само ако двете страни са дали предварително писмено съгласие за това. Решенията са били окончателни, не подлежали на обжалване и се привеждали в изпълнение от кмета.

Възстановителните подходи и практики и сега може да се използват в наказателните процеси, най-вече когато извършители на правонарушения са младежи. Не е спорно, че децата извършители на деяния, които осъществяват състав на престъпление, в изключителен случай следва да влизат в затвора, защото поначало са жертви на лошо възпитание, социална занемареност, домашно насилие и т.н. Стремежът на общностите е насочен към усилието да се въздейства навреме и с минимална принуда върху поведението на личностите в процес на физиологично и социално формиране, като по този начин да се преодолеят криминогенните фактори, които са били в основата на правонарушението, без да се нанесат нови травми, неоправдани за постигане на целите на правосъдието.

Опитът на държавите с развити помирителни системи показва, че участието на непълнолетните във възстановителни програми, самостоятелно или наред с наказанието, има благоприятно възпитателно въздействие и е реална превенция на престъпността. Българската традиция не е чужда и на това разбиране. В периода 1943–1948 г. действа Закон за съдилища за маловръстни, в който е уредена система за съчетаване на възпитателни мерки с наказанието под контрола от съда.

Възстановителното правосъдие е шанс в България да се справим с липсата на доверие в съдебната власт, с нарастващото отчуждение на гражданите от институциите и с девалвацията на държавната принуда в резултат на погрешна наказателноправна политика – увеличаването на наказанията, без да се дава отговор на въпросите защо се прави това и каква обществена полза би донесло. Създаването на различни по вид възстановителни програми ще има стимулиращ ефект и за изграждане на животоспособна социална инфраструктура с развитие на разнообразни и адекватни на нуждите социални услуги, която да извършва рехабилитация на извършителите на престъпления.

Заглавна снимка: Priscilla Du Preez / Unsplash

Източник

The collective thoughts of the interwebz